I'm trying to asssert that a method was called on a stub. The method I'm trying to assert was called takes an IEnumerable<string>
. I don't care about the exact contents, but I just want to test that the count is a certain number. I can't get the assertion correct, I get
Rhino.Mocks.Exceptions.ExpectationViolationException : Bob.DoThings(collection count equal to 10); Expected #1, Actual #0.
I know that DoThings() is indeed being called... I just can't get the constraint correct..
var myBob= MockRepository.GenerateStub<Bob>();
var countConstraint = Rhino.Mocks.Constraints.List.Count(Rhino.Mocks.Constraints.Is.Equal(10));
// execution code....
Joe myJoe = new Joe(myBob);
myJoe.MethodThatShouldCallDoThingWith10();
myBob.AssertWasCalled(s => s.DoThings(null), o => Constraints(countConstraint));
I've also tried adding "IgnoreArguments" as a constraint. What am I missing?
The issue here is with deferred execution. It's not until the IEnumerable<string>
is enumerated that the list of items is "built". Since Rhino.Mocks just records what gets called, it never "uses" the method arguments and therefore, the list is never built nor enumerated. As you've seen, adding a ToList() or ToArray() enumerates and builds the list so the test will pass if you use one of those methods.
One workaround is to grab the list that was passed to the method and do your check on that:
var list = (IEnumerable<int>) myBob.GetArgumentsForCallsMadeOn(b => b.DoThings(null))[0][0];
Assert.AreEqual(10, list.Count());
This test passes and doesn't require any changes to your code.
This problem was alredy reported Here. I've been able to reproduce this problem with the following Bob and Joe:
public interface Bob
{ void DoThings(IEnumrable<int> list); }
public class Joe
{
private readonly Bob bob;
public Joe(Bob bob)
{ this.bob = bob; }
public void MethodThatShouldCallDoThingWith10()
{
var values = Enumerable.Range(1, 100).Where(x => x > 0 && x < 11);
bob.DoThings(values);
}
}
It seems there's some problem in Rhino Mocks after all, when it comes to LINQ: either report the bug to Ayende or add ToList() in your production code (not really recommended)...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With