The coding blog of Alastair Smith, a software developer based in Cambridge, UK. Interested in DevOps, Azure, Kubernetes, .NET Core, and VueJS.
To aid the testing of my personal finance program, I’ve been making heavy use of the NMock mocking framework for .NET. This is a cool utility that allows you replace actual code calls with mock code calls, factoring out a lot of complexity of setting up some tests. For example, I first started using it to mock the log4net logging framework rather than creating a new logger for each test/suite and passing that around. More recently, I’ve found it useful in mocking parts of the plug-in framework that are required by the code but not part of the test (such as the preferences’ manager, for example). By way of example, here’s set-up method from one of my plug-ins’ test suite:
Expect.Number_Of_Times.On(mock_object)
. As you can see, the statements read very much like English, which I think is one of the strengths of the framework. You can immediately tell what the expectation of this object is without having to think around the syntax of the framework. Note too the heavy use of interfaces: NMock can only mock interfaces, which I think is another strength of the framework. This focus on interfaces really drives to you programming via interfaces, which is a key part of designing by contract.
So what does this code do? First of all, it creates a Mockery
object, which is essentially a factory object for mock objects. Next, a mock logger and mock plug-in framework object are created. A real PreferencesManager
is created, and we tell NMock that we expect exactly 4 calls to logger.Info in the Initialise
method of PreferencesManager
. The same is done for a PluginBroker
and its Initialise
method. Notice here that we're specifying too that the property PluginBroker.PreferencesManager
will return a specific value, i.e., the PreferencesManager
created earlier. A MessageBroker
is then created in the same way. Finally, we state that we expect the properties MessageBroker
, PluginBroker
and PreferencesManager
on pluginFramework
will return the concrete objects already created.
At the end of each test, which may contain further expectations of our mocked objects, we can run Mockery.VerifyAllExpectationsHaveBeenMet()
, which does exactly what it says on tin (a victory for clear over concise method naming!). Note, however, that this is an instance method and not a static one, so you'll need to call it on the Mockery
object created at the beginning.
NMock has a certain amount of flexibility in its interface. For example, you can replace Expect.x
with Stub
, which is equivalent to Expect.AtLeast(0)
. There is also a raft of quantifiers for expectations in addition to Once
and AtLeast(x)
, such as Between(x, y)
and Never
.
The downside of NMock is that your expectations end up littered with strings referencing parts of the API. If a mocked part of the API changes, you have to update these so-called "magic" strings with the appropriate new values; it also enforces a certain amount of trial and error when initially testing your expectations. A framework like Rhino Mocks will use the compiler to tell you when you've messed up by allowing you to reference the mocked properties on the mock object directly, e.g.: