Rhino Mocks:在存根上为方法重新分配新结果

时间:2020-03-06 14:37:23  来源:igfitidea点击:

我知道我可以这样做:

IDateTimeFactory dtf = MockRepository.GenerateStub<IDateTimeFactory>();
dtf.Now = new DateTime();
DoStuff(dtf); // dtf.Now can be called arbitrary number of times, will always return the same value
dtf.Now = new DateTime()+new TimeSpan(0,1,0);  // 1 minute later
DoStuff(dtf); //ditto from above

如果不是IDateTimeFactory.Now是属性而是方法IDateTimeFactory.GetNow(),该怎么办,我该怎么做?

根据以下犹大的建议,我将我的SetDateTime helper方法重写如下:

private void SetDateTime(DateTime dt) {
        Expect.Call(_now_factory.GetNow()).Repeat.Any();
        LastCall.Do((Func<DateTime>)delegate() { return dt; });
    }

但它仍然抛出" ICurrentDateTimeFactory.GetNow();的结果已经设置。"错误。

再加上它仍然无法与存根一起使用。

解决方案

我们可以使用Expect.Call完成此操作。这是使用记录/播放模型的示例:

using (mocks.Record())
{
   Expect.Call(s.GetSomething()).Return("ABC"); // 1st call will return ABC
   Expect.Call(s.GetSomething()).Return("XYZ"); // 2nd call will return XYZ
}
using (mocks.Playback())
{
   DoStuff(s);
   DoStuff(s);
}

好的,所以我的第一个答案对我们不起作用,因为GetSomething可能会被多次调用,而我们却不知道调用了多少次。

我们在这里遇到了一些复杂的情况-方法调用的数量未知,但是在调用DoSomething之后会有不同的结果-我建议我们将单元测试简化一些,否则我们将不得不为单元测试准备单元测试。 :-)

失败了,这是我们可以完成想要做的事情的方法:

bool shouldReturnABC = true;
using (mocks.Record())
{
   Expect.Call(s.GetSomething()).Repeat.Any();

   LastCall.Do((Func<string>)delegate()
   {
      return shouldReturnABC ? "ABC" : "XYZ";
   }
}
using (mocks.Playback())
{
   DoStuff(s);
   shouldReturnABC = false;
   DoStuff(s);
}

乔治,

使用我们更新的代码,我可以正常工作:

MockRepository mocks = new MockRepository();

[Test]
public void Test()
{
    IDateTimeFactory dtf = mocks.DynamicMock<IDateTimeFactory>();

    DateTime desiredNowTime = DateTime.Now;
    using (mocks.Record())
    {
        SetupResult.For(dtf.GetNow()).Do((Func<DateTime>)delegate { return desiredNowTime; });
    }
    using (mocks.Playback())
    {
        DoStuff(dtf); // Prints the current time    
        desiredNowTime += TimeSpan.FromMinutes(1);  // 1 minute later    
        DoStuff(dtf); // Prints the time 1 minute from now
    }
}

void DoStuff(IDateTimeFactory factory)
{
    DateTime time = factory.GetNow();
    Console.WriteLine(time);
}

FWIW,我不相信我们可以使用存根来完成此任务;我们需要改用模拟。