Wednesday, April 30, 2014

Making Moq Better...

TL;DR;  (Too Long Don't Read)

I wrote an extension for Moq to assert that no methods are called on a mock object.

Moq is great ...

Moq is my favorite mocking framework for C#, but it's not perfect.

I like it because it supports test Spies (to use Martin Fowlers terms).

Test Spies remember interactions, so you can assert on them at the end of the test instead of setting up your expectations at the beginning of the test. Some people don't like this as your feedback comes after the faulty code has been executed, instead of being at the point the unexpected interaction occurs, so you don't have the same stack trace, What it does, however, is allow you to follow the Arrange, Act, Assert pattern for test construction. This in turn allows you to strictly limit the focus of your tests, making them less brittle and more intention revealing.

But ...

If you want to assert that no interactions occurred with an object, this standard way of doing this in Moq is to use a "strict" mock. A Strict mock will throw exceptions when a method you didn't explicitly set up is called.

Strict mode is set at object construction which is typically in your setup method, so can't be changed on a per test basis. This means all tests make this interaction implicit assertion even the ones where the focus of the test isn't on these interactions.

Even worse, say you "setup" some default behaviour for your Stub object, Now if you want to know that no methods are called on a specific test, then you have to explicitly "verify" each method individually to assert it's not called. This makes tests brittle. If you add a new method to the object you have to add that methods to any test that was asserting that no interactions occurred.

Extension Methods To the Rescue!

To help with this I have written an extension method to verify no methods are called on an object.

This useful, but is only a step in the right direction. Ideally you would be able to specify all the interactions you do want to occur, and finish by saying "and nothing else".

No comments:

GitHub Projects