OdeToCode IC Logo

A Gentle Introduction to Mocking

Thursday, April 17, 2008

At the last CMAP Code Camp I did a "code-only" presentation entitled "A Gentle Introduction to Mocking". We wrote down some requirements, opened Visual Studio, and started writing unit tests. Matt Podwysocki provided color commentary. Code download is here.

I started "accepting" mock objects as one tool in my unit testing toolbox about three years ago (see "The 5 Stages Of Mocking"). Times have changed quite a bit since then, and the tools have improved dramatically. During the presentation we used the following:

Rhino Mocks – the first mocking framework used in the presentation. Years ago, Oren and Rhino Mocks saved us from "string based" mock objects. Rhino Mocks can easily conjure up a strongly typed mock object. The strong typing results in fewer errors, and greatly enhances the refactoring experience.

moq – is the latest mocking framework in the .NET space and is authored by kzu and friends. moq uses lambda expressions and expression trees to define mock object behavior, and also provides strongly typed mocks. The recent addition of factories and mock verification means you can do traditional interaction style testing with moq, if that is the path you choose. The primary differentiator between the two frameworks is that moq does not use a record / playback paradigm.

Here is a test we wrote with Rhino Mocks:

[Fact]
public void Does_Not_Make_Deposit_When_Verification_Fails()
{
    
MockRepository mocks = new MockRepository();
    
IAuditService auditService = mocks.DynamicMock<IAuditService>();
    
IVerificationService verificationService = mocks.CreateMock<IVerificationService>();

    
decimal amount = 1000;
    
BankAccount account = new BankAccount(auditService,
                                          verificationService);

    
using (mocks.Record())
    {
        
Expect.Call(verificationService.VerifyDeposit(account, amount))
              .Return(
false);

    }

    
using (mocks.Playback())
    {
        account.Deposit(amount);
    }

    account.Balance.ShouldEqual(0);

}

The same test using moq:

[Fact]
public void Does_Not_Make_Deposit_When_Verification_Fails()
{
    
Mock<IAuditService> _auditMock = new Mock<IAuditService>();
    
Mock<IVerificationService> _verificationMock = new Mock<IVerificationService>();

    
decimal amount = 1000;
    
BankAccount account = new BankAccount(_auditMock.Object, _verificationMock.Object);


    _auditMock.Expect(a => a.WriteMessage(
It.IsAny<string>()));
    _verificationMock.Expect(v => v.VerifyDeposit(account, amount))
                     .Returns(
false);

    account.Deposit(amount);
    account.Balance.ShouldEqual(0);            
}

xUnit.net – although not featured in the presentation, xUnit.net drove all the unit tests. xUnit is a new framework authored by Jim Newkirk and Brad Wilson. The framework codifies some unit testing best practices and takes advantage of new features in the C# language and .NET framework. I like it.

One question that came up a few times was "when should I use a mock object framework"? Turns out I've been asked a lot of questions starting with when lately, so I'll answer that question in the next post.