2011-04-10 62 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;