Since my team started in with mocking about a year ago, we decided to go with NMock2 despite the magic strings. The mocking frameworks at the time looked pretty similar, and for our needs, the simplicity of NMock2 was a good fit. We have been re-evaluating our choice of tools as of late to ensure we are still using best of breed. Some quick googling turned up this good and relatively recent comparison of mocking frameworks, which turned us onto NMock3.
This post highlights the compelling difference between NMock2 and NMock3 (aside from the fact that NMock2 isn’t being actively developed any more) and provides a quick example of how to migrate from NMock2 to NMock3.
The Setup
To demonstrate the basics of NMock2, NMock3, and the migration process, I’ve created two simple projects: one that represents an application, and the other that represents the tests.
Our BizLayerTests project has a ReferencedDLLs folder with our needed external testing libraries, NMock2 and NUnit. The tests project has references to these two libraries and our project under test.
Our class hierarchy will also be simple, consisting of one business object that has a dependency on a data access layer that is injected via the business object’s constructor. The class diagram is below.
The SomeBizCount property on the BizObject is lazy loaded via the GetSomeCount method on the IBizRepo interface. The criteria is based on the bizObjectName that is passed in when the BizObject is created.
The Test
We aspire to not having our tests touch the database unless we are writing them directly against our repositories. We use mocks to effect this, and will do so for our simple case above. The NMock2 test looks like below.
using NUnit.Framework;
using Is = NUnit.Framework.Is;
using NMock2;
using BizLayer;
namespace BizLayerTests
{
[TestFixture]
public class BizObjectTests
{
[Test]
public void SomeBizCountIsLazyLoadedTest()
{
Mockery mockery = new Mockery();
IBizRepo mockRepo = mockery.NewMock<IBizRepo>();
Expect.Once.On(mockRepo).Method("GetSomeCount")
.With("bizobjectname").Will(Return.Value(42));
BizObject b = new BizObject("bizobjectname", mockRepo);
Assert.That(b.SomeBizCount, Is.EqualTo(42));
mockery.VerifyAllExpectationsHaveBeenMet();
}
}
}
The first thing to note here is our imports at the top. As our practice our team imports the Is identifier explicitly from the NUnit libraries to avoid a naming collision with the NMock2 library. NUnit provides an Iz identifier to help with this, but we prefer to suffer the extra import and maintain trivial readability.
The next thing to note is the magic string that we use when setting up the expectations on our mock. We specify that we expect the method GetSomeCount will be called once, but GetSomeCount is a string literal, which is less than optimal.
Another thing to notice is the call to VerifyAllExpectationsHaveBeenMet. This is NMock2’s way of allowing the test writer to ensure that all coded expectations have been met. This has a slight code smell to it, as it’s a catch all method that isn’t directly expressive in and of itself.
The final thing to notice is the location of our assertions regarding what has to happen on our mocks to satisfy the test. Given that our test follows the AAA syntax, we see that we assert what has to happen (namely that the GetSomeCount method is called once) in the arrange section of our test. We won’t be addressing this issue in this post, that’s for the follow up when we start talking about Moq.
Migrating to NMock3
The writers of NMock3 kept the namespace the same, namely NMock2. While confusing at first, they were wanting to make upgrading from 2 to 3 as painless as possible. They also kept the same NMock2 syntax in place, so in theory all we have to do is swap out the NMock2 library for the NMock3 library and reset our reference.
The first step here is to download NMock3. For this example we’ll be using the 3.5 framework version, Beta 6. Once we have this, we copy it over to our ReferencedDLLs folder in our test project, giving us something like below.
Because of NMock3 using the NMock2 namespace, we can’t reference both libraries at the same time. To get our new library in play, we have to delete the current NMock2 reference and then add a reference to the NMock3 dll. Once we do this, we can run our test… at least one would think. But then we get the below.
The interface definition in our test project is indeed marked public, which makes the above exception even more puzzling. Some quick googling produces hits like this and this that make reference to the InternalsVisibleTo attribute. Adding this, however, didn’t clear the exception. At this point we are definitely working too hard to try and get something working that we in essence already have working in NMock2. Curiosity demands that we try a simple fix however, namely the 4.0 framework version, also Beta 6. Downloading this version and replacing the NMock3.dll we have and re-adding the reference, amazingly enough, gets our test working.
Mocking NMock3 Style
Now that we’re past that hubbub, and ignoring the odd behavior of the 3.5 framework version of NMock3, we can demonstrate the compelling reason that NMock3 is better than NMock2 – no more magic strings. Our test, mocked in NMock3 style, is below.
[Test]
public void SomeBizCountIsLazyLoadedTest2()
{
MockFactory mf = new MockFactory();
Mock<IBizRepo> mockRepo = mf.CreateMock<IBizRepo>();
mockRepo.Expects.One.Method(m => m.GetSomeCount(""))
.With("bizobjectname").Will(Return.Value(42));
BizObject b = new BizObject("bizobjectname", mockRepo.MockObject);
Assert.That(b.SomeBizCount, Is.EqualTo(42));
mf.VerifyAllExpectationsHaveBeenMet();
}
We see that NMock3 has introduced lambda notation when setting expectations on a mock, which allows us to eschew magic strings and brings in more compile-time checking for our tests.
The Final Verdict
Given the fact that my team has our projects targeting the 3.5 framework, the upgrade to NMock3 isn’t as compelling as it would otherwise be without the mysterious “inaccessible interface” error above. If it weren’t for this error upgrading to NMock3 would be a no-brainer, especially considering that NMock2 syntax is fully supported out of the box. For my team in particular, any effort spent trying to figure out this issue simply doesn’t present a strong enough case to upgrade.
That said, there was another point made in the post cited at the beginning of this post by someone who worked on NMock2 originally that leads us to the next post that will contrast the NMockX way to the Moq way.
Moving From NMock2 to NMock3…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
[...] be starting with the code that we spun up in my prior post regarding moving from NMock2 to NMock3. The NMock3 version of the test that we’ll be using to [...]
[...] that looks very interesting but I can’t see the documentation (the INsecurity system). See http://www.barebonescoder.com/2010/07/moving-from-nmock2-to-nmock3/ for more details. I think I like Moq best, but I need to check the others somewhere where I can [...]