Setup Moq To Return Multiple Values

本秂侑毒 提交于 2019-12-25 18:15:25

问题


I am new to Moq and I want to have a test like this:

[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();
        }

It throws this:

------ 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).

The actual code under test:

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

But if I only call to the service once it works, but the service only gets the first value.

Also if I debug and mouse over the httpContext.Request.UserHostAddress, the value changes.

Any ideas?

Edit #1

So I found the issue I think. This issue is that the actual code under test loops through all the ip's and doing that calls the UserHostAddress. I just really need to figure out how to supply an array of strings into the Returns() function of the mock.


回答1:


Your UserHostAddress property might be called few times in call to Any, and we do not know how many times it's gonna be called (depends on content of internalAddressRoots). So by the time you get to the second service call, your queue might be empty.

If you really want to test twice, maybe you should setup twice. Subsequent setups override previous ones:

    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();
    }

As you see, we're mixing setup with the assert part, which doesn't look that good, but I'm not sure about your motives, so here's one possible solution.



来源:https://stackoverflow.com/questions/12484241/setup-moq-to-return-multiple-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!