Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rhino mocks: Issue with IEnumerator.MoveNext() when stubbing an IEnumerable<T> interface

Our API has an interface inheriting from IEnumerable like this:

public interface IFoos : IEnumerable<IFoo>
{
    // Additional foo-collection-specific methods
}

I'm writing a unit test for a class that depends on IFoos. It has a method that iterates on an IFoos, like this:

public class Bar
{

    public IFoos Foos {get; set;}
    public void FooItUp()
    {
        foreach (IFoo foo in this.Foos)
        {
            foo.JumpAround();
        }
    }
}

In my unit test, I manage to stub out the dependency and return an Enumerator with Rhino Mocks like so:

[Test]
public void FooItUp_JumpsUpJumpsUpAndGetsDown()
{
    // Arrange
    var mocks = new MockRepository();
    var stubFoo1 = mocks.Stub<IFoo>();
    var stubFoo2 = mocks.Stub<IFoo>();
    var stubFoos = mockRepository.Stub<IFoos>().
    var fooEnumerator = new List<IFoo> { stubFoo1, stubFoo2 }.GetEnumerator();
    stubFoos.Stub(x => x.GetEnumerator()).Return(null).WhenCalled(x => x.ReturnValue = fooEnumerator);
    Bar bar = new bar();
    bar.Foos = stubFoos;

    // Act
    bar.FooItUp();

    // Assert
    ...

}

When I try running this test, an exception is thrown:

System.InvalidOperationException : Previous method 'IEnumerator.MoveNext();' requires a return value or an exception to throw.

Looking at the IEnumerable interface, though, the only method I should have to implement or set a return value for is GetEnumerator() which I did above, right? Why doesn't the foreach loop in Bar.FooItUp() just call MoveNext() on the List enumerator?

like image 609
System.Cats.Lol Avatar asked Mar 07 '11 18:03

System.Cats.Lol


2 Answers

Durrr.

I wasn't putting my stubs in replay state before acting on them.

Adding the line:

mocks.ReplayAll();

before calling bar.FooItUp() fixed the issue.

like image 182
System.Cats.Lol Avatar answered Sep 19 '22 21:09

System.Cats.Lol


Try changing:

stubFoos.Stub(x => x.GetEnumerator()).Return(null).WhenCalled(x => x.ReturnValue = fooEnumerator); 

To:

stubFoos.Stub(x => x.GetEnumerator()).Return(fooEnumerator);

Edit: interesting info in that question you linked.

Having looked at it, try:

stubFoos.Stub(x => x.GetEnumerator()).Return(null).WhenCalled(x => x.ReturnValue = new List<IFoo> { stubFoo1, stubFoo2 }.GetEnumerator()); 
like image 33
Phil Sandler Avatar answered Sep 16 '22 21:09

Phil Sandler