使用Moq模拟一个Func<>构造函数参数和验证它被调用两次

时间:2013-02-06 12:43:29

标签: c# unit-testing moq functional-testing

从本文(How to moq a Func)中提取问题并对其进行调整,因为答案不正确。

public class FooBar
{
    private Func<IFooBarProxy> __fooBarProxyFactory;

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

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

我需要模拟一个Func&lt;&gt;作为构造函数参数传递,断言func被调用两次。

当试图模拟函数var funcMock = new Mock<Func<IFooBarProxy>>();时Moq引发异常,因为Func类型不可模拟。

问题在于,如果没有模拟func,就无法验证函数是否被调用(n)次。 funcMock.Verify( (), Times.AtLeast(2));

3 个答案:

答案 0 :(得分:32)

我认为没有必要为Func使用模拟。

您可以自己创建一个普通的Func,返回模拟IFooBarProxy

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

var sut = new FooBar(func);

sut.Process();

Assert.Equal(2, numberOfCalls);

答案 1 :(得分:19)

至少从Moq 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));
}

答案 2 :(得分:4)

自Moq v4.1.1308.2120

以来

此版本是在问题被提出几个月后发布的(2013年8月21日),模拟Func<> has been added的功能。因此,对于任何当前版本的模拟,您可以使用var funcMock = new Mock<Func<IFooBarProxy>>();

原创(过时)回答

如果您有很多回调FuncActions等,最好在测试中定义帮助程序界面并模拟该界面。这样您就可以使用常规Moq功能,例如设置返回值,测试输入参数等等。

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));