2012-05-23 15 views
18

我期待找出如何我可以模擬一個方法,第二次調用第一次返回一個不同的值時間。例如,類似這樣的東西:RhinoMocks - 嘲笑一個方法,其返回值更改(即使傳遞相同的參數)與多個調用

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?

乾杯傢伙,

亞歷

+0

看看有序和無序的嘲笑:http://ayende.com/wiki/Rhino%20Mocks%20Ordered%20and%20Unordered.ashx – Maciej

+2

你提供的代碼有什麼問題? 'Repeat.Once()'應該可以工作 –

+0

@lazyberezovsky對m.SecondsSinceStarted的第一次調用返回2,而不是1按預期方式 – AlexC

回答

28

您可以攔截返回值與.WhenCalled方法。請注意,您仍然需要通過.Return方法來提供價值,但是犀牛將簡單地忽略它,如果ReturnValue從方法調用改變:

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。

+0

據我所知,除了序列號之外的東西,他應該通過索引創建數組和返回值? –

+0

我同意這種方法的工作原理,但這基本上與必須實現一個狀態機相同,我提到了我試圖避免的狀態機。如果我想在第二次調用時返回11,那麼我需要做一些事情,如「if(invocationsCounter == 1)return 1; else if(invocationsCounter == 2)return 11;」看起來非常像狀態機。 – AlexC

+0

Re:你的編輯。不知道這是否是在我正在使用的RhinoMocks版本中改變的某些功能,但是我已經運行了原始問題中的測試,並且可以告訴它它失敗了(即第一次調用SecondsSinceStarted返回2)。你有沒有鏈接到你發現它的工作? – AlexC

0

時間是什麼方法返回的決定性因素?如果是這樣,我會試着抽出時間段,以便在測試中直接控制它。

類似於名爲ITimeProvider的接口,其成員名爲GetElapsedTime(),然後創建一個默認實現以在整個應用程序中使用。

然後,當您測試時,傳入一個模擬的ITimeProvider,以便控制應用程序感知的時間。

+0

真的,時間的事情只是一個方便的例子,沒有完全描述我試圖測試什麼。儘管如此,如果我想模擬一個帶有GetElapsedTime()方法的ITimeProvider,如果我想編寫一個調用GetElapsedTime()兩次的單元測試,並且希望我的模擬ITimeProvider返回一個不同的值每次通話的時間。 – AlexC

+0

你可以讓ITimeProvider成爲財產依賴嗎?因此能夠在每次電話會議之前注入​​新的嘲笑?即使如此,如果它不是你處理的時間,我的答案可能是毫無價值的...... – theMothaShip

+0

我的問題是關於RhinoMocks是否支持這種與生成的模擬/存根的交互,而不是我如何解決它,如果不支持。不過謝謝。 – AlexC

5

只需使用

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

本次通話過程中會返回第一個通話期間12。至少在RhinoMocks 3.6.0.0上

+0

這當然與我在上面運行測試時看到的衝突 – AlexC

+0

正如接受的答案中所提到的,這是正確的,我的測試只是失敗,因爲我正在逐步進行評估,並且無意中評估了某些內容。 Upvoted。 – AlexC

相關問題