2013-02-06 40 views
18

從這篇文章中採納了這個問題(How to moq a Func)並將其作爲答案進行了修改,因爲答案不正確。使用Moq來模擬Func <>構造函數參數並驗證它被調用了兩次

public class FooBar 
{ 
    private Func<IFooBarProxy> __fooBarProxyFactory; 

    public FooBar(Func<IFooBarProxy> fooBarProxyFactory) 
    { 
     _fooBarProxyFactory = fooBarProxyFactory; 
    } 

    public void Process() 
    { 
     _fooBarProxyFactory(); 
     _fooBarProxyFactory(); 
    } 
} 

我有一個需要模擬函數求<>被作爲構造函數參數傳遞,該FUNC是調用兩次斷言。

當試圖模擬功能var funcMock = new Mock<Func<IFooBarProxy>>(); Moq引發和異常,因爲Func類型不可模仿。

問題是,如果不嘲笑函數,就不可能驗證函數被調用了(n)次。 funcMock.Verify((), Times.AtLeast(2));

+0

Moq現在支持OP最初試圖做的事情,請參閱@ ktam33的答案 – Mike

回答

27

我不認爲有必要爲Func使用模擬。

您可以簡單地創建一個普通的函數功能自己返回的IFooBarProxy一個模擬:

int numberOfCalls = 0; 
Func<IFooBarProxy> func =() => { ++numberOfCalls; 
            return new Mock<IFooBarProxy>(); }; 

var sut = new FooBar(func); 

sut.Process(); 

Assert.Equal(2, numberOfCalls); 
2

由於起訂量v4.1.1308.2120

由於這個版本,這是發佈了一些個月後,這一問題被問(2013年8月21日),功能模擬Func<>has been added。因此,對於任何當前版本的模擬,您可以使用var funcMock = new Mock<Func<IFooBarProxy>>();

原件(過時)答案

如果你有很多回調Func的,Actions等,這是更好地定義你的測試一個助手接口和模擬該接口。這樣,您就可以使用常規的起訂量的功能,如設置了返回值,測試輸入參數等

interface IFooBarTestMethods 
{ 
    IFooBarProxy FooBarProxyFactory(); 
} 

使用

var testMethodsMock = new Mock<IFooBarTestMethods>(); 
testMethodsMock 
    .Setup(x => x.FooBarProxyFactory()) 
    .Returns(new Mock<IFooBarProxy>()); 

var sut = new FooBar(testMethodsMock.Object.FooBarProxyFactory); 
testMethodsMock.Verify(x => x.FooBarProxyFactory(), Times.Exactly(2)); 
6

由於至少起訂量4.5.28,你可以模擬並驗證Func,就像你期望的那樣。我無法分辨何時添加了此功能(根據原始問題,在某些時候這不起作用)。

[Test] 
public void TestFoobar() 
{ 
    var funcMock = new Mock<Func<IFooBarProxy>>(); 
    var fooBar = new FooBar(funcMock.Object); 
    fooBar.Process(); 
    funcMock.Verify(x => x(), Times.AtLeast(2)); 
}