38

从这篇文章(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<>,即 func 被调用两次的断言。

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

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

4

3 回答 3

40

我认为没有必要为 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);
于 2013-02-06T12:45:11.543 回答
32

至少从起订量 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));
}
于 2017-03-03T21:12:47.723 回答
7

从起订量 v4.1.1308.2120

在这个问题被问到几个月后(2013 年 8 月 21 日)发布的这个版本中,添加了模拟 a 的Func<> 功能。因此,对于任何当前版本的 mock,您都可以使用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));
于 2016-09-02T09:30:24.453 回答