Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rhino Mock List constraint

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?

like image 929
Stealth Rabbi Avatar asked Sep 22 '11 18:09

Stealth Rabbi


2 Answers

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.

like image 158
PatrickSteele Avatar answered Nov 03 '22 08:11

PatrickSteele


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

like image 2
Amittai Shapira Avatar answered Nov 03 '22 09:11

Amittai Shapira