I am using Moq paired with an Interface of methods. I need to test that the methods in this interface are executed in a certain sequence as well as a certain number of times for each one.
public interface IInterface
{
void MethodOne(string foo);
void MethodTwo(string foo);
}
// MyClass stuff ...
public async Task Run()
{
MethodOne("foo");
MethodTwo("foo");
}
// ...
I've written this test to verify that the methods are only executed a certain amount of times (once):
[TestMethod]
public async Task Test()
{
var mock = new Mock<IInterface>();
var mockSequence = new MockSequence();
var obj = new MyClass();
await obj.Run();
mock.Verify(i=> i.MethodOne("foo"), Times.Once());
mock.Verify(i=> i.MethodTwo("foo"), Times.Once());
}
This works fine...
I've tried these tests for determining a certain sequence is properly met, but the test seems to always pass.
[TestMethod]
public async Task Test()
{
var mock = new Mock<IInterface>();
var mockSequence = new MockSequence();
var obj = new MyClass();
await obj.Run();
mock.InSequence(mockSequence).Setup(i => i.MethodOne("foo"));
mock.InSequence(mockSequence).Setup(i => i.MethodTwo("foo"));
}
Should pass, and does...
[TestMethod]
public async Task Test()
{
var mock = new Mock<IInterface>();
var mockSequence = new MockSequence();
var obj = new MyClass();
await obj.Run();
mock.InSequence(mockSequence).Setup(i => i.MethodTwo("foo")); // swapped order here
mock.InSequence(mockSequence).Setup(i => i.MethodOne("foo"));
}
Should not pass, but does...
A mock execution is a stratagem in which a victim is deliberately but falsely made to feel that their execution or that of another person is imminent or is taking place. The subject is made to believe that they are being led to their own execution.
Sequential mocking allows you to return different values on the same or different consecutive calls to one and the same type. In other words, you can set up expectations for successive calls of the same type.
Or the sequence of calls to an object. Moreover, it checks the communications among classes. We can use the method mock () for mocking purposes. Subsequently, let us see the implementation for testing of mock objects via the Mockito framework.
When you’re mocking a method that’s called multiple times, you may want to change the behavior of the method each time it’s called. The way you do this with Moq is by using SetupSequence (), like this: mock.SetupSequence (t => t.ShouldRetry ()).Returns (true).Returns (true).Returns (false); Code language: C# (cs)
Your example tests for InSequence
seem to be in the wrong order. You should be performing the Setup
, before you invoke the Run
method. I've assumed this is a typo and that your actual tests do the Setup
, then invoke the object in the correct order. It's also not clear how your mock of IInterface
gets to MyClass
. In my final example, I've assumed it's actually injected...
Moq's InSequence
support only seems to work if you're using strict mocks. If you create your Mock
like this:
var mock = new Mock<IInterface>(MockBehavior.Strict);
Then this will work:
mock.InSequence(mockSequence).Setup(i => i.MethodOne("foo"));
mock.InSequence(mockSequence).Setup(i => i.MethodTwo("foo"));
while this fails:
mock.InSequence(mockSequence).Setup(i => i.MethodTwo("foo")); // swapped order here
mock.InSequence(mockSequence).Setup(i => i.MethodOne("foo"));
Note, the error that comes is about the method missing a corresponding setup... rather than it being called out of sequence, which isn't necessarily the easiest to decode if you're not expecting it.
The alternate approach, if you don't want to / can't use strict mocks is to implement your own sequence checking using callbacks. Something like this:
int sequence = 1;
mock.Setup(i => i.MethodOne("foo"))
.Callback(()=>Assert.AreEqual(1, sequence++, "Method called out of sequence"));
mock.Setup(i => i.MethodTwo("foo"))
.Callback(() => Assert.AreEqual(2, sequence++, "Method called out of sequence"));
var obj = new MyClass(mock.Object);
await obj.Run();
This may be further off topic than you want to go but NSubstitute is a great mocking library that handles this very well. In NSubstitute it's just:
var mock = Substitute.For<IInterface>();
var obj = new MyClass();
await obj.Run();
Received.InOrder(() => {
mock.MethodOne("foo");
mock.MethodTwo("foo");
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With