Search code examples
c#unit-testingmockingrhino-mocks

Rhino Mocks - mocking a method whose return value changes (even when passed the same parameter) with multiple calls


I'm looking to find out how I can mock a method that returns a different value the second time it is called to the first time. For example, something like this:

public interface IApplicationLifetime
{
    int SecondsSinceStarted {get;}
}

[Test]
public void Expected_mock_behaviour()
{
    IApplicationLifetime mock = MockRepository.GenerateMock<IApplicationLifetime>();

    mock.Expect(m=>m.SecondsSinceStarted).Return(1).Repeat.Once();
    mock.Expect(m=>m.SecondsSinceStarted).Return(2).Repeat.Once();

    Assert.AreEqual(1, mock.SecondsSinceStarted);
    Assert.AreEqual(2, mock.SecondsSinceStarted);
}

Is there anything that makes this possible? Besides implementing a sub for the getter that implements a state machine?


Solution

  • You can intercept return values with the .WhenCalled method. Note that you still need to provide a value via the .Return method, however Rhino will simply ignore it if ReturnValue is altered from the method invocation:

    int invocationsCounter = 1;
    const int IgnoredReturnValue = 10;
    mock.Expect(m => m.SecondsSinceLifetime)
        .WhenCalled(mi => mi.ReturnValue = invocationsCounter++)
        .Return(IgnoredReturnValue);
    
    Assert.That(mock.SecondsSinceLifetime, Is.EqualTo(1));
    Assert.That(mock.SecondsSinceLifetime, Is.EqualTo(2));
    

    Digging around a bit more, it seems that .Repeat.Once() does indeed work in this case and can be used to achieve the same result:

    mock.Expect(m => m.SecondsSinceStarted).Return(1).Repeat.Once();
    mock.Expect(m => m.SecondsSinceStarted).Return(2).Repeat.Once();
    mock.Expect(m => m.SecondsSinceStarted).Return(3).Repeat.Once();
    

    Will return 1, 2, 3 on consecutive calls.