问题
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