Moq, argument matching and Times.Never

Consider the following test code that is using Moq:

private void VerifyRequestWasNotLogged()
		r =>
					l =>
						l.CurrentNumber == 0 && l.OriginalNumber == 0 &&
						l.Extension == string.Empty && l.OrderId == null &&
						l.OrderRef == null &&
						l.Url == Url)), Times.Never, "Wrong request.");

Not going too much into details, what this method does is verify that _logRepository.LogRequest was never called. The tests that were using this check were always green, but after some time, we found out that there actually are entries in the logs that were supposed not to be there. Can you spot the problem with this code?

In our case, there was a change in the code that changed the default value of RequestLogData.Extension property from string.Empty to null. Quite an innocent one and it didn’t break the tests. However, looking at the check above, there is a condition “l.Extension == string.Empty”. So the verification will never throw an exception, even if there is an undesirable call to _logRepository.LogRequest somewhere in the code under test. To the verification, the method is never called.. with the data specified 🙂

Looking at this and many more examples that I’ve seen, I’d say that Times.Never should rarely be combined with argument matching. Or, at least, the matching rules should be as loose as possible to avoid situations where it is not clear why it passes – because the method is not never called, or because the arguments don’t match on the called methods.

Have you ever been bitten by tests like this one? 🙂


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s