c# - Moq 验证方法失败,即使方法将被调用

标签 c# .net unit-testing mocking moq

我在使用 Moq 时遇到了一些麻烦。后续单元测试抛出异常,即使相应的方法将被调用。

[TestMethod]
public void CreateFinishTest() {
    // mock methods 
    factoryMock.Setup(f => f.LoadPlan("TestPlanDoNotUse")).Returns(testPlan).Verifiable();
    factoryMock.Setup(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>())).Returns(testFinish.Id).Verifiable();

    try {
        var cfm = new CreateFinishMessage() {
            ClientId = 11,
            MessageId = 23456,
            CustomerId = 6,
            FinishName = "MyFinish",
            PlanId = "TestPlanDoNotUse"
        };
        var cmd = sysCfg.Executor.CreateFinish(cfm); // calls LoadPlan with cfm.PlanId and CreateFinish with cfm and cfm.PlanId
        sysCfg.Executor.Execute(cmd);

        factoryMock.Verify(f => f.LoadPlan("TestPlanDoNotUse"), Times.Exactly(1));
        factoryMock.Verify(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>()), Times.Exactly(1));
    } catch (Exception exc) {
        Assert.Fail(exc.Message);
    }
}

发生此错误:

Expected invocation on the mock exactly 1 times, but was 0 times: f => f.LoadPlan("TestPlanDoNotUse")

Configured setups:
f => f.LoadPlan("TestPlanDoNotUse"), Times.Once

Performed invocations:
IFactory.LoadPlan("TestPlanDoNotUse")
Factory.CreateFinish(IndiValue.LiveMarket.IndiCore.Communication.MessagingFormat.CreateFinishMessage, "MyFinish")

我已经尝试了几种不同的 Verify-Calls,但都行不通。发生的错误似乎很令人困惑,它说 LoadPlan("TestPlanDoNotUse") 从未被调用,但它在 @Performed invocations 中列出。

问题解决:

我想我发现了问题,这不是最小起订量问题。在 sysCfg.Executor.CreateFinish(cfm) 中创建并启动了一个新线程。此线程未完成,因此 factoryMock.Verify(...) 失败。

我使用了 AutoResetEvents:

// create AutoResetEvent triggers
AutoResetEvent m_testTrigger1 = new AutoResetEvent(false);

// mock methods     
factoryMock.Setup(f => f.LoadPlan(It.IsAny<string>())).Returns(testPlan).Callback(() => m_testTrigger1.Set());

// do something

// wait for triggers
bool didReturn1 = m_testTrigger1.WaitOne(timeOut);

最佳答案

在 Verifiable 未被调用时,重要的是您期望中的参数与生产代码使用的参数相匹配。

关于 Thread.Sleep 的使用,请尽可能避免它,因为它只会减慢测试速度以满足您最慢的机器。我通常将 WaitHandles 引入到我的测试中,以确保测试运行得与代码一样快。

拍一个peek here on a small utility将 WaitHandles 与事件一起使用。

关于c# - Moq 验证方法失败,即使方法将被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6184566/

相关文章:

c# - 在 Lucene 中搜索 TokenStream 字段

c# - 使用 Dispose() 从 Form 中删除 Control

c# - 检测项目是否正在为 windows 8 或 wp 编译

c# - 在 Visual Studio 中打开项目/解决方案和打开网站有哪些区别?

c# - Task.WhenAny 是否将某些任务优先于其他任务?

c# - 支持 C#/VB.NET 的日期和时间库?

c# - 来自 PInvoke 的 x64 C 函数中的重叠内存地址

在类中使用的 Python 模拟 os.environ

unit-testing - Symfony2 在单元测试中获取配置参数

python - 如何在 Python (2.7) 单元测试中参数化 setUpClass()