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?
Cheers fellas,
Alex
You can intercept return values with .WhenCalled
method. Note that you still need to provide value via .Return
method, however Rhino will simply ignore it if ReturnValue
is altered from 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));
Edit:
Digging around a bit more, it seems that .Repeat.Once()
does indeed work in this case and can be used to achieve 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.
Simply use
mock.Expect(m=>m.SecondsSinceStarted).Return(1).Repeat.Once();
mock.Expect(m=>m.SecondsSinceStarted).Return(2).Repeat.Once();
This will return 1
during first call, and 2
during second call. At least on RhinoMocks 3.6.0.0
Is time the determining factor in what the method returns? If so, I would try to abstract out the time passage so you have direct control over it in your tests.
Something like an interface called ITimeProvider with a member called GetElapsedTime() and then create a default implementation to use throughout your application.
Then when you are testing, pass in a mocked ITimeProvider so you control what is perceived by your application to be time passed.