2011-04-10 55 views
9

我在阅读Roy Osherove的单元测试艺术时开始试验Rhino-Mocks(3.6)。他有证明模拟的方法可以编写脚本返回不同的结果与相同的参数调用两次时的例子:使用Rhino-Mock存根的订购方法返回值

[Test] 
    public void ReturnResultsFromMock() 
    { 
     MockRepository repository = new MockRepository(); 
     IGetRestuls resultGetter = repository.DynamicMock<IGetRestuls>(); 
     using(repository.Record()) 
     { 
      resultGetter.GetSomeNumber("a"); 
      LastCall.Return(1); 

      resultGetter.GetSomeNumber("a"); 
      LastCall.Return(2); 

      resultGetter.GetSomeNumber("b"); 
      LastCall.Return(3); 

     } 

     int result = resultGetter.GetSomeNumber("b"); 
     Assert.AreEqual(3, result); 

     int result2 = resultGetter.GetSomeNumber("a"); 
     Assert.AreEqual(1, result2); 

     int result3 = resultGetter.GetSomeNumber("a"); 
     Assert.AreEqual(2, result3); 
    } 

这工作得很好。但是,当我尝试用存根,并接受并返回一个字符串的方法同样的事情,我不能够产生第二返回值:

[Test] 
    public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived() 
    { 
     MockRepository mocks = new MockRepository(); 
     IMessageProvider stub = mocks.Stub<IMessageProvider>(); 

     using (mocks.Record()) 
     { 
      stub.GetMessageForValue("a"); 
      LastCall.Return("First call"); 
      stub.GetMessageForValue("a"); 
      LastCall.Return("Second call"); 
     } 

     Assert.AreEqual("First call", stub.GetMessageForValue("a")); 
     Assert.AreEqual("Second call", stub.GetMessageForValue("a")); 
    } 
} 

public interface IMessageProvider 
{ 
    string GetMessage(); 
    string GetMessageForValue(string value); 
} 

这个测试失败,因为“第一呼叫”是收到这两个电话。我已经尝试了几种语法的折痕(使用mocks.Ordered(),SetResult,Expect等),但我仍然无法获得第二个结果出现。

我做错了什么,或者这是Rhino-Mocks的限制吗?我检查了blog post,但是建议的语法并未解决我的问题。

回答

10

你错过了该位告诉第一个值应仅使用一次返回的存根:

... 
using (mocks.Record()) 
{ 
    stub.GetMessageForValue("a"); 
    LastCall.Return("First call").Repeat.Once(); 
    stub.GetMessageForValue("a"); 
    LastCall.Return("Second call"); 
} 

当然你的“第二个电话”的真正含义“第二或-后续调用”除非你可以用Repeat重复其他限制。

您还可以考虑使用较新的安排,法,断言(AAA)语法RhinoMocks现在提供:

[Test] 
public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived() 
{ 
    IMessageProvider stub = MockRepository.GenerateStub<IMessageProvider>(); 

    stub.Expect(mp => mp.GetMessageForValue("a")) 
     .Return("First call") 
     .Repeat.Once(); 
    stub.Expect(mp => mp.GetMessageForValue("a")) 
     .Return("Second call"); 

    Assert.AreEqual("First call", stub.GetMessageForValue("a")); 
    Assert.AreEqual("Second call", stub.GetMessageForValue("a")); 
} 

这是一个小更简洁,一般不必担心记录回放 - 为您节省断言存根的状态。 Derick Bailey在Los Techies上写了一篇article about using Repeat。它也恰好使用AAA语法)。

+1

@先生腻子,谢谢! Repeat.Once()很好地工作。 – 2011-04-10 05:32:02

+0

+1文章...我一直在寻找一个很好的综合解释,现在:) – 2012-10-31 13:27:52

1

我想如果你正在使用存根,使用Expect不适合,因为你不想要一个期望,而是一个替代你的依赖。

所以我相信,如果你使用存根语法更有意义:

stub.Stub.(s=>s.GetMessageForValue("a")) 
          .Return("First call").Repeat.Once(); 

stub.Stub.(s=>s.GetMessageForValue("a")) 
          .Return("Second call").Repeat.Any;