开发者

Moq verify method fails even though method will be called

I have some troubles using Moq. Following unit test throws an exception, even though the according method will be called.

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

This Error occurs:

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

I've tried several different Verify-Calls but it won't work. And the Error which occurs seems quite confusing it's says that LoadPlan("TestPlanDoNotUse") is never called, but it's listed @ Performed invocations.

Problem solved:

I think i found the problem, it wasn't a Moq problem. In sysCfg.Executor.CreateFinish(cfm) a new thread was created and started. This thread wasn't finished and so factoryMock.Verify(...) failed.

I used 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开发者_Python百科 triggers
bool didReturn1 = m_testTrigger1.WaitOne(timeOut);


On the Verifiable not being called, it's important that the arguments in your expectation match the arguments that are being used by the production code.

Regarding the use of Thread.Sleep, avoid it wherever possible as it will only slow down the tests to meet your slowest machine. I typically introduce WaitHandles into my tests to ensure that the tests run as fast as the code.

Take a peek here on a small utility that uses WaitHandles with events.


You do not usually use Verifiable() in your setups in conjuction with the Verify(expr, times) methods. Does it work if you remove the .Verifiable() calls?


I guess this is a me-too answer, but I believe this to be a simpler solution than many of the mentioned before.

I implemented a WaitFor function which utilizes a lambda callback to evaluate a condition:

public static void WaitFor(Func<bool> action, long timeoutMillis = 10000) { Stopwatch elapsed = Stopwatch.StartNew(); elapsed.Start(); // ReSharper disable once LoopVariableIsNeverChangedInsideLoop while (!action()) { if (elapsed.ElapsedMilliseconds > timeoutMillis) { throw new TimeoutException("Timed out waiting for condition to become true after " + elapsed.ElapsedMilliseconds + " ms"); } Thread.Sleep(0); } }

and the test code looks like this:

    [Test]
    public void ShouldNackUnparsableInboundMessage()
    {   
        var nackCalled = false;
        _mock.Setup(m => m.BasicNack(999, false, false)).Callback(() =>
        {
            nackCalled = true;
        });

        ... do whatever which invokes the call on another thread.

        WaitFor(() => nackCalled);
        // Test will fail with timeout if BasicNack is never called.
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜