-
-
Notifications
You must be signed in to change notification settings - Fork 798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Verify calls are made in the correct order #748
Comments
This comment has been minimized.
This comment has been minimized.
Hmm, on second thought, please disregard the above post. You said that you don't want to Another little-known Moq feature you could use is argument capturing (e.g. var args = new List<string>();
mock.Setup(m => m.Method(Capture.In(args)));
// ...
Assert.SequenceEqual(new[] { "a1", "a2", "b1", "a3" }, args); Note that a call to |
I've read about MockSequence before, but in my case it works worse than using callbacks. [Test]
public void GIVEN_play_invoked_twice_with_first_play_too_early_canceled_EXPECTED_commands_send_in_proper_order()
{
// Arrange
var wavPath = F.Create<string>();
var wavPath2 = F.Create<string>();
var playId = F.Create<string>();
void Act()
{
// Act
_sut.PlayWave(wavPath);
_sut.CancelPlay();
_sut.OnPlayStarted(playId);
_sut.OnPlayComplete(playId);
_sut.PlayWave(wavPath2);
}
void SetAssertions()
{
// Assert
SetVerification(sender => sender.PlayWave(AssertPlayParameters(wavPath)), invocationOrder: 0);
SetVerification(sender => sender.CancelPlay(AssertCancelParameters(playId)), invocationOrder: 1);
SetVerification(invoker => invoker.OnPlayComplete(), invocationOrder: 2);
SetVerification(sender => sender.PlayWave(AssertPlayParameters(wavPath2)), invocationOrder: 3);
}
SetAssertions();
Act();
AssertVerifications();
} In private void AssertVerifications()
{
Assert.AreEqual(_expectedInvocationsNumber, _invocationsNumber, "Methods were not invoked expected number of times");
Assert.IsTrue(_invocationOrderIsCorrect, "Wrong methods invocation order");
} Tests written with those methods look acceptably, but still much worse than tests which doesn't need to check order of invocations, for example to comparision [Test]
public void GIVEN_play_invoked_twice_but_play_started_and_play_complete_not_came_EXPECTED_only_first_play_sent()
{
// Arrange
var wavPath = F.Create<string>();
var wavPath2 = F.Create<string>();
// Act
_sut.PlayWave(wavPath);
_sut.PlayWave(wavPath2);
// Assert
_mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath)), Times.Once);
_mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath2)), Times.Never);
} Update: it might be not obvious, but in first shown test, 'invoker' and 'sender' are two different dependencies ( |
Short of
You mentioned briefly that you don't want to Finally, what exactly are you requesting here? Is this issue simply a question about available solutions given the current APIs, or are you requesting a new feature? (If the latter, what should that hypothetical feature look like to be useful to you?) |
I thought that I thought that extending current For example: var seq = new MocksSequence();
_mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath)), seq, invocationOrder: 0);
_mockInvoker.Verify(sender => invoker.OnPlayComplete(), seq, invocationOrder: 1); Or something fluent: var seq = new MocksSequence();
_mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath))).CallOrder(seq, 0);
_mockInvoker.Verify(sender => invoker.OnPlayComplete()).CallOrder(seq, 1); Or something like this: new MocksSequence()
{
() => _mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath))),
() => _mockInvoker.Verify(sender => invoker.OnPlayComplete())
}.VerifyInvocationOrder(); Or some static way: Mock.InSequence(() => _mockProtocolSender.Verify(sender => sender.PlayWave(AssertPlayParameters(wavPath))));
Mock.InSequence(() => _mockInvoker.Verify(sender => invoker.OnPlayComplete()); So it's feature request :) |
Yes, public interface IFoo
{
void Do();
}
var seq = new MockSequence();
var a = new Mock<IFoo>(MockBehavior.Strict);
var b = new Mock<IFoo>(MockBehavior.Strict);
a.InSequence(seq).Setup(m => m.Do())...;
b.InSequence(seq).Setup(m => m.Do())...;
a.Object.Do();
b.Object.Do(); This example uses What this won't do—and that's one example of a.Verify(m => m.Do(), Times.Once);
b.Verify(m => m.Do(), Times.Once);
The fundamental problem with all of your examples is that there is no global fully ordered record of all mock invocations; in fact, each mock only keeps track of its own invocations, so we have no record of whether a call to So at the very least, you'd have to have some way of telling each mock The most minimal, but still feasible API when we want to focus on // Arrange:
var a = new Mock<IFoo>();
var b = new Mock<IFoo>();
var seq = MockSequence.With(a, b); // sets up `a` and `b` such that they report all calls to `seq`
// Act:
a.Object.Do();
b.Object.Do();
// Assert:
// verifications on `seq` must happen in the same order as the recorded calls:
seq.Verify(() => a.Do(), Times.Once);
seq.Verify(() => b.Do(), Times.Once);
seq.VerifyNoOtherCalls(); This is off the top of my head, without looking at #21 and #75. I am sure there's a ton of use cases I'm forgetting about—e.g. cyclic sequences—for which the above example would be a bad fit. |
I'm aware of it, every example I've given has some 'higher' state. |
I use great
Verify
method often, but sometimes I need to check not only how many times given method was invoked, but also if it was in proper order.Sometimes even with mixing order of different mocks, for example
Currently I use work around basing on callbacks (like posted in stack overflow https://stackoverflow.com/questions/10602264/using-moq-to-verify-calls-are-made-in-the-correct-order)
But it has big disadvantage, that I need to prepare assertions before acting, which looks strange. The best I can do is to wrap it in local functions which make it look a bit better, but it's still inconvenient
The text was updated successfully, but these errors were encountered: