【问题标题】:Setup Moq To Return Multiple Values设置 Moq 以返回多个值
【发布时间】:2012-09-18 20:10:24
【问题描述】:

我是 Moq 的新手,我想进行这样的测试:

[Fact]
        public void IsClientExternalForWebShouldReturnFalse()
        {
            // Arrange
            var request = new Mock<HttpRequestBase>();
            request.Setup(r => r.UserHostAddress).Returns(new Queue<string>(new[] { "127.0.0.1", "10.1.10.1" }).Dequeue);

            var context = new Mock<HttpContextBase>();
            context.SetupGet(c => c.Request).Returns(request.Object);

            var service = new EnvironmentService(context.Object, null);

            // Act / Assert
            service.IsClientExternal.Should().BeFalse();
            service.IsClientExternal.Should().BeFalse();
        }

它抛出这个:

------ Test started: Assembly: SAIF.Services.Tests.dll ------

Test 'SAIF.Services.Tests.EnvironmentServiceTests.IsClientExternalForWebShouldReturnFalse' failed: System.InvalidOperationException : Queue empty.
    at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
    at System.Collections.Generic.Queue`1.Dequeue()   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
    at System.Collections.Generic.Queue`1.Dequeue()   at Moq.Extensions.InvokePreserveStack(Delegate del, Object[] args)
    at Moq.MethodCallReturn`2.Execute(ICallContext call)
    at Moq.Interceptor.Intercept(ICallContext invocation)
    at Moq.Proxy.CastleProxyFactory.Interceptor.Intercept(IInvocation invocation)
    at Castle.DynamicProxy.AbstractInvocation.Proceed()
    at Castle.Proxies.HttpRequestBaseProxy.get_UserHostAddress()
    Services\EnvironmentService.cs(54,0): at SAIF.Services.EnvironmentService.<get_IsClientExternal>b__3(String ip)
    at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
    Services\EnvironmentService.cs(54,0): at SAIF.Services.EnvironmentService.get_IsClientExternal()
    EnvironmentServiceTests.cs(25,0): at SAIF.Services.Tests.EnvironmentServiceTests.IsClientExternalForWebShouldReturnFalse()

0 passed, 1 failed, 0 skipped, took 0.69 seconds (xUnit.net 1.9.1 build 1600).

实际测试代码:

public bool IsClientExternal
        {
            get { return IsWeb && !internalAddressRoots.Any(ip => httpContext.Request.UserHostAddress.StartsWith(ip)); }
        }

但是如果我只在它工作后调用服务,但服务只获取第一个值。

此外,如果我调试并将鼠标悬停在 httpContext.Request.UserHostAddress 上,值会发生变化。

有什么想法吗?

编辑#1

所以我发现了我认为的问题。这个问题是被测试的实际代码循环通过所有 ip 并调用UserHostAddress。我只需要弄清楚如何将字符串数组提供给 mock 的 Returns() 函数。

【问题讨论】:

  • 为什么要测试几次?
  • @Bartosz - 我需要确保测试给定数量的 IP。

标签: unit-testing moq


【解决方案1】:

您的UserHostAddress 属性可能会在调用Any 时被调用几次,我们不知道它会被调用多少次(取决于internalAddressRoots 的内容)。因此,当您进行第二次服务呼叫时,您的队列可能是空的。

如果你真的想测试两次,也许你应该设置两次。后续设置会覆盖之前的设置:

    public void IsClientExternalForWebShouldReturnFalse()
    {
        // Arrange
        var request = new Mock<HttpRequestBase>();
        request.Setup(r => r.UserHostAddress).Returns("127.0.0.1");

        var context = new Mock<HttpContextBase>();
        context.SetupGet(c => c.Request).Returns(request.Object);

        var service = new EnvironmentService(context.Object, null);

        // Act / Assert
        service.IsClientExternal.Should().BeFalse();

        request.Setup(r => r.UserHostAddress).Returns("10.1.10.1");
        service.IsClientExternal.Should().BeFalse();
    }

如您所见,我们将 setup 与 assert 部分混合在一起,看起来不太好,但我不确定您的动机,所以这是一种可能的解决方案。

【讨论】:

  • 没错!我很快就明白了。有任何想法吗?您认为测试中的 for 循环来测试每个 IP 是否可以?我知道你应该只Assure 一次,但实际上这是一个正在测试的条件。
  • 使用解决方案更新了答案,以在同一属性上使用多个设置。不是很好,但我仍然不确定你为什么需要这样做两次。
  • 基本上我需要为多个 ip 运行这个测试。我应该有单独的测试吗? SetupSequence 呢?
  • 我只需要两个单独的测试并从一个通用的上下文基类派生它们。
猜你喜欢
  • 2015-12-14
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 2021-06-28
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多