Moq Sequence with Callback C#

久未见 提交于 2020-12-12 05:12:53

问题


I have this code below with a simple nunit test using Moq Sequence. The unit test works without using Callback, but it fails with Callback. Any ideas?

public class MoqDemo
{
    private ISender sender;

    public MoqDemo(ISender sender)
    {
        this.sender = sender;
    }

    public void Send()
    {
        for (int i = 0; i < 3; i++)
        {
            sender.SendMessage(i, $"{i}");
        }
    }
}

NUnit test

[TestFixture]
public class MoqDemoTest
{
    [Test]
    public void SequenceTest()
    {
        var sender = new Mock<ISender>();

        using (Sequence.Create())
        {
            var demo = new MoqDemo(sender.Object, repository.Object);
            sender.Setup(s => s.SendTrade(2, "1")).InSequence(Times.Never());

            sender.Setup(s => s.SendTrade(0, "0"))
                .InSequence()
                .Callback<int, string>((id, msg) =>
            {
                Debug.WriteLine(msg);
            });

            sender.Setup(s => s.SendTrade(1, "1")).InSequence();
            sender.Setup(s => s.SendTrade(2, "2")).InSequence();
            demo.Send();
        }
    }
}

The test failed at sender.Setup(s => s.SendTrade(1, "1")).InSequence(); Error message is "Expected invocation on the mock once, but was 0 times: ''Moq.Language.Flow.VoidSetupPhrase`1[MoqDemo.ISender]'"

However if I remove the callback, it works

UPDATE:

Went through the Moq Sequence source code and found the problem using this callback and InSequence pattern.

Internally, the InSequence() method registers the Moq's Callback method automatically for the sequence checking logic. Therefore, if I do .Callback directly in my unit test, it will override the original callback for sequence checking. When running the unit test, as the expected sequence is established in the setup phase and Moq.Sequence expects ALL automatically generated Callback to be called, therefore, the unit test fails.

I extended the SequenceExtensions.cs in Moq-Sequence and it works as expected now

public static ISetup<T> InSequence<T, T1, T2>(this ISetup<T> 
setup, Action<T1, T2> callback) where T : class
{
    var step = Sequence.Step(setup, Times.Once());
    setup.Callback<T1, T2>((id, msg) =>
    {
        Sequence.Record(step);
        callback(id, msg);
    });
    return setup;
}

来源:https://stackoverflow.com/questions/54342383/moq-sequence-with-callback-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!