2013-11-01 40 views
3

我有一個在foreach循環內多次調用的方法,每次使用相同的參數值。如何使FakeItEasy僞造對象的方法拋出第一次調用並返回第二個?

foreach (var item in myCollection) 
{ 
    // do some stuff with item 
    // then... 
    var result = _myService.Foo(aConstant, anotherConstant); 
    // do something with result 
} 

我試圖寫一個測試,以確保繼續循環迭代即使_myService.Foo()拋出在第一時間通過一個例外。

Moq,允許我一起鏈呼籲ReturnsThrows像這樣:

mockService.Setup(x => x.Foo(aConstant, anotherConstant)).Throws<Exception>().Returns(someResult); 

這將導致調用Foo拋出一個異常,但所有後續調用將返回someResult。我的主要目標是確保try/catch塊在我的foreach塊中的第二部分代碼周圍,這樣即使發生異常也能繼續循環。

foreach (var item in myCollection) 
{ 
    // do some stuff with item 
    // then... 
    try 
    { 
     var result = _myService.Foo(aConstant, anotherConstant); 
     // do something with result 
    } 
    catch (Exception e) 
    { 
     // ignore any exceptions here and continue looping 
    } 
} 

我該如何在FakeItEasy中完成類似的操作?或者是否有一種不同的(更好的)策略可以用來做這種斷言?

回答

9

這有點不直觀,但如果你先設置了退貨,那麼拋出一個.Once,它的作品。您可以在FakeItEasy文檔中閱讀關於limited call specifications的更多信息。

我喜歡把它看作是「在最後的勝利」,所以正常的當然是返回一個值,但隨後我們用一次性例外

public interface IFoo 
{ 
    int Do(); 
} 

[Test] 
public void ThrowsFirstTime() 
{ 
    var fakeFoo = A.Fake<IFoo>(); 
    A.CallTo(() => fakeFoo.Do()).Returns(1); 
    A.CallTo(() => fakeFoo.Do()).Throws<Exception>().Once(); 

    Assert.Throws<Exception>(()=>fakeFoo.Do()); 
    int t = fakeFoo.Do(); 

    A.CallTo(() => fakeFoo.Do()).MustHaveHappened(Repeated.Exactly.Twice); 
    Assert.That(t, Is.EqualTo(1)); 
} 
+0

這個工程完全按照預期取代。我也嘗試過你的例子,改變它以再次調用Do()幾次,以確保它在第一次後不會再次拋出異常,但事實並非如預期的那樣。謝謝! –

1

在情況下,它可以幫助別人......

我想出了一個辦法與void返回類型的方法做到這一點。我用Invokes()方法:

A.CallTo(() => _fakeService.VoidMethod(aConstant, anotherConstant)) 
          .Invokes(ThrowExceptionOnFirstInvocation); 

那麼測試方法外,我所定義的ThrowExceptionOnFirstInvocation功能:

private void ThrowExceptionOnFirstInvocation(IFakeObjectCall obj) 
{ 
    if (_numInvocations++ == 0) throw new Exception(); 
} 

private int _numInvocations; 

我仍然不知道如何爲這雖然返回的東西的方法做到這一點。

相關問題