Loose expectations with NMock2

November 23rd, 2006 | Tags: ,

NMock2 will have a verification failure if all expected calls are not made and if any unexpected calls are made. That last bit can make writing test code rather tedious.

I have a presenter and I’m testing its normal path using a bunch of calls like the following:

Expect.Once.On(view).GetProperty("Name").Will(Return.Value("Widget"));
Expect.Once.On(view).GetProperty("Quantity").Will(Return.Value(3));
Expect.Once.On(view).GetProperty("Price").Will(Return.Value(9.95m));
Expect.Once.On(view).Method("ShowTotal").With(29.85m);

That’s all good, but now I want to test some error conditions, exceptions, bad input, etc., but I dont want to repeat all the property test, especially considering the maintenance issues—if I add a new call to another property in my presenter, all my tests will fail because there was an unexpected call. It would be much nicer to only have to change one test instead of many. Not to mention that testing the same thing ten times is rather stinky.

As far as I could tell, NMock2 doesnt allow for this type of loosely coupled mock, so I found a way to coerce NMock2 into doing it.

NMock2 supports a Stub method that sets an anything expectation (i.e., zero or more), but if you do something like Stub.On(view); any specific expectations you set afterward are meaningless and will never fail.

What you need to do is create an negative method matcher for the stub so it sets an anything expectation for all methods but the one you wish to set a specific expectation on:

private Matcher Not(string methodName)
{
    return new NotMatcher(new MethodNameMatcher(methodName));
}
...
Stub.On(view).Method(Not("ShowError"));
Expect.Once.On(view).Method("ShowError").With(Strings.Invalid_Quantity);

I’ll leave the implementation for doing the same thing, but for multiple methods to the reader. Clue: you’ll need to us an or matcher.

No comments yet.

TOP