Reputation: 15771
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.
Upvotes: 0
Views: 2545
Reputation: 3358
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.
Upvotes: 2