22

我正在寻找如何模拟第二次调用第一次返回不同值的方法。例如,像这样:

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);
}

有什么可以让这成为可能吗?除了为实现状态机的 getter 实现 sub 之外?

4

3 回答 3

36

.WhenCalled您可以使用该方法拦截返回值。请注意,您仍然需要通过.Return方法提供一个值,但是如果ReturnValue从方法调用中更改,Rhino 将简单地忽略它:

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

再挖掘一下,似乎在这种情况下.Repeat.Once() 确实有效,并且可以用来实现相同的结果:

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();

将在连续调用时返回 1、2、3。

于 2012-05-23T13:44:42.413 回答
7

只需使用

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

这将1在第一次调用2期间和第二次调用期间返回。至少在 Rhino Mocks 3.6.0.0 中。

于 2012-05-23T15:30:54.050 回答
0

如果时间是方法返回的决定因素,我会尝试抽象出时间流逝,以便您在测试中直接控制它。

类似于一个名为 ITimeProvider 的接口和一个名为 GetElapsedTime() 的成员,然后创建一个默认实现以在整个应用程序中使用。

然后,当您进行测试时,传入一个模拟的 ITimeProvider,这样您就可以控制应用程序感知到的时间。

于 2012-05-23T14:26:43.703 回答