Reputation: 4100
With Moq, it is possible to verify that a method is never called with certain arguments (that is, arguments satisfying certain predicates) using Times.Never
.
But how to verify that, no mater how many times a method is called, it is always called with certain arguments?
The default appears to be Times.AtLeastOnce
.
There is no Times.Always
. Am I missing something obvious? Thanks!
Edit: I posted a suggestion to the Moq mailing list last week, but it doesn't look like it's been moderated yet. I'll post any updates here.
Edit: an example. Say I am testing a class which generates XML documents. I want to ensure that only valid documents are generated. In other words, test that the writer dependency is only ever given valid documents, with a valid sequence number, to write.
should_only_write_valid_xml_documents
Mock.Get(this.writer).Verify(
w => w.Write(
It.Is<XDocument>(doc => XsdValidator.IsValid(doc)),
It.Is<int>(n => n < 3)),
Times.Always);
Upvotes: 6
Views: 785
Reputation: 1875
You can apply inversion of logic to verify ALWAYS.
E.g.:
Let's say you want to do the following verification:
mock.Verify(x => x.Method(It.Is<int>(i => i == 10)), Times.Always());
you can simply replace it with:
mock.Verify(x => x.Method(It.Is<int>(i => i != 10)), Times.Never());
Upvotes: 2
Reputation: 25523
It sounds like you're wanting "Strict" mock behavior. If the method is called with anything other than the expected parameters, the test will fail.
This is available in Moq:
var mock = new Mock<IFoo>(MockBehavior.Strict);
(Example taken from the Moq QuickStart.)
Every invocation on the mock must now have a corresponding Setup
.
Using strict mocks tends to lead to brittle tests. I would avoid this technique, or at least use it sparingly.
Upvotes: 3
Reputation: 27495
My recommendation would be to create a 'fallback' matching for the method with It.IsAny conditions. You can then verify Times.Never on that matching, which should always have been superseded by the more specific match.
Upvotes: 0
Reputation: 2416
And how many times is 'always?' Moq keeps track of all the times a certain method is called with certain arguments, and then uses that number for comparing to Times.Never, Times.AtLeastOnce, etc.
So, if a method is executed 4 times and you set it to 'Times.Always' what does that even mean?
Times.Never would check to make sure the number is zero.
Times.AtLeastOnce would check that the number is greater than or equal to one.
Times.Always would check that the number is.... ?
You could determine the number of times it SHOULD run programmatically, then do something like:
Times.Exactly(calculatedAmount)
But there is no way for Moq to know what 'always' means.
Upvotes: 8