First try of NMock2

When unit testing you should try to test the class of interest in isolation, this means removing any dependencies with other components; for example I needed to test in isolation a class that is instanciated by passing to it an object that implements IDataReader.

public DictionaryItem(IDataReader)

By creating a mock object for IDataReader, the class can be tested in isolation of the Data Access Layer (DAL).

You could either create the necessary mock object, by building your own class implementing IDataReader or use a mock object framework to help you.
For some time now NMock has been regarded as a powerful framework for generating mock objects, however the original NMock had a few limitations, one of which seemed to prevent nmock from being used to test a class that exposed an indexer. Fortunately NMock2 the new version of nmock, solves this problem. NMock2 is a total re-write micking jMock were “expectations are expressed in a more conversational style”; this makes NMock to easier to work with than its predecessor.

The following code creates the dataReaderMock mock object, which can then be passed to my DictionaryItem class in my unit test;

Mockery mocks = new Mockery();

IDataReader dataReaderMock = (IDataReader)mocks.NewMock(typeof(IDataReader));

Expect.AtLeastOnce.On(dataReaderMock).Method(”Read”).Will(Return.Value(true));
Expect.Once.On(dataReaderMock).Method(”Read”).Will(Return.Value(false));
Expect.Once.On(dataReaderMock).Method(”NextResult”).Will(Return.Value(false));
Expect.Once.On(dataReaderMock).GetProperty(”IsClosed”).Will(Return.Value(false));
Expect.Once.On(dataReaderMock).Method(”Close”);

Expect.Once.On(dataReaderMock).Get[”COL_1″].Will(Return.Value(4));
Expect.Once.On(dataReaderMock).Get[”COL_2″].Will(Return.Value(”col1ValueExpectedByUnitTest”));
Expect.Once.On(dataReaderMock).Get[”COL_3″].Will(Return.Value(”col2ValueExpectedByUnitTest”));
return dataReaderMock;

As you can see the expectations on a Mock2 object are easy to read; at least one expectation is made for each propety or method you expect to be called. The expectations reflect how the constructor of DictionaryItem will use the IDataReader; in my case the mock object reflects an DataReader with only one DataRow. The first part of the expectation defines how many times you expect the method to be called “Expect.AtLeastOnce.On”, the second part defines the name of the method, property or indexer expected to be called “Method(”Read”)” and the last part defines what value should be returned “Will(Return.Value(true))”.
If you use the mock object an nunit test if any of the expectations have not been met, the test will fail.

Download NMock2, NMock2 Tutorial

Test-Driven Development in Microsoft  .NET (Microsoft Professional)

Bookmark on del.icio.us

3 Comments »

  1. Paul Kinlan said,

    June 28, 2006 @ 2:50 pm

    Would it not be simpler and more reusable to create a Stub DataReader and Stub Record Collection that could fake the results from the DB, so that you can check the data parsing works correctly.

    Much like: http://www.haacked.com/archive/2006/05/31/UnitTestingDataAccessCodeWithTheStubDataReader.aspx

  2. dibbin said,

    July 7, 2006 @ 8:23 pm

    Thanks for being the first none spam comment on my blog.

    The stub data reader in the article you mentioned, provides an good way replacing your db for testing and depending on the circumstances, may be more suitable than using NMock, especially if you wanted a more generic solution.

    The article also highlights some of the benefits of using NMock: Without NMock we would have to build stubs in a similar way to the StubDataReader implementing all members; you can see by comparing the amount of code above to the StubDataReader that this is a considerable time saving. NMock also allows us to say exactly how an object will be used, what properties/methods will be called, how many times etc.

  3. Paul Kinlan said,

    March 21, 2007 @ 12:19 pm

    Every NMock 2 search I do comes up with this, lucky really because I need to do indexers in NMock2. :)

RSS feed for comments on this post · TrackBack URI

Leave a Comment