Unit Testing and Mock Frameworks

I’m not a big fan of Test Driven Development (TDD), but I love Unit Testing.

But to be productive on unit testing I need a good framework for Mock Objects. I can’t expect to be productive and have to build a lot of mock classes to test other classes. And, who tests the mock classes?

Mock objects simulate the behavior of real objects when they are difficult or impossible to obtain.

I’ve been testing a few mock frameworks and this is my opinion (*) on the ones I’ve tested.

NMock

I’ve been introduced to NMock by Jean-Paul Boodhoo and his series of articles (MSDN) and shows (dnrTV).

NMock is an open source project that you can use, providing you abide to their conditions.

NMock is expectation based and has one really neat feature that I like: the ability to scope the mocks. I can write a test like this:

using (Mockery mockery = new Mockery())

{

    ISomeInterface instance = mockery.NewMock<ISomeInterfac>();

    Expect.Once.On(instance).Method(“SomeMethod”).With(Is.EqualTo(SomeValue)).Will(Return.Value(true));

    Assert.IsTrue(instance.SomeMethod(SomeValue));

}

As you can see, you just define a mock scope by instantiating a Mockery object and disposing of it in the end. In between, you just declare what you expect to happen.

What I don’t like is the fact that I don’t have compile time checking on the mocked members. If I need to do some refactoring on ISomeInterface I will have to go all over my tests and change the strings defining ISomeInterface‘s members.

At this time NMock doesn’t handle mocking Generics, which makes it useless to me.

Support is mainly provided through a community group.

NMock also seems to be a dead project at this time.

Rhino.Mock

Through MockObjects.com I came to Rihno.Mocks. Rihno.Mocks is the result of Ayende‘s open source project and free to use, providing you abide to his conditions.

As I understand it, Rhino.Mocks has dropped the scope feature present in NMock but, besides the expectation mechanism, it has a recording mechanism. It’s as easy as follows:

MockRepository mocks = new MockRepository();

 

IDemo demo = mocks.CreateMock<IDemo>();

// Setting up an expectation for a call to IDemo.VoidNoArg   

demo.VoidNoArg();   

mocks.ReplayAll();   

// Fullifying the expectation for call to IDemo.VoidNoArg   

demo.VoidNoArg();

 

mocks.VerifyAll();

However, the last version of Rhino.Mocks I tested didn’t support mocking Generics, which (as I said before) makes it useless to me. But there’s hope, a new version is on the way.

Support is mainly provided through a community group.

TypeMock.NET

This is my favorite. Have you ever thought you could do this?

string username = “test”;

 

using (RecordExpectations recorder = RecorderManager.StartRecording())

{

    recorder.ExpectAndReturn(HttpContext.Current.ApplicationInstance.User.Identity.Name, username);

}

 

string expected = username;

 

Assert.AreEqual(expected, HttpContext.Current.ApplicationInstance.User.Identity.Name);

 

TypeMock.MockManager.Verify();

Well, you will on the next release.

And you can mock classes with generic methods:

public class Test { public T DoIt<T>(T t) { return t; } }

 

[TestMethod()]

public void NaturalMockTest()

{

    MockManager.Init();

    Mock testMock = MockManager.Mock(typeof(Test));

 

    Test t = new Test();

 

    Assert.AreEqual(3, t.DoIt(3));

    Assert.AreEqual(“something”, t.DoIt(“something”));

}

TypeMock has 3 versions: Community, Professional and Enterprise. The Community version is free but you will have to pay for the other two.

TypeMock supports two types of mocks: Reflective Mocks and Natural Mocks™.

TypeMock‘s Reflective Mocks by declaring the behavior of classes using its members’ names:

public bool IsAuthenticated(string name, string password)

 

{

    Logger.Log(Logger.NORMAL, “Entering Authentication”);

    try

    {

        // do something

        int Results = DoSelect(statement);

        bool isOk = Results == 1;

        if (isOk)

        {

            Logger.Log(Logger.NORMAL, “User Authenticated “ + name);

        }

        else

        {

            Logger.Log(Logger.SECURITY, “User login failed “ + name);

        }

        return isOk;

    }

    catch (Exception ex)

    {

        Logger.Log(Logger.FAILED, “Login system failure”, ex);

        // handle exception

    }

}

 

[TestMethod]

public void Authenticated()

{

    Authentication authenticator = new Authentication();

    // Initialize Type Mocks (This can be done in the [Setup])

    MockManager.Init();

    // the Logger class is now being mocked

    Mock logMock = MockManager.Mock(typeof(Logger));

    // set up our expectations for 2 Log calls in IsAuthenticated

    // 1) “Entering Authentication” Log at first line

    // 2) “User login failed user” Log

    logMock.ExpectCall(“Log”);

    logMock.ExpectCall(“Log”);

 

    // authentication should fail

    Assert.IsFalse(authenticator.IsAuthenticated(“user”, “password”));

    // Verify that all calls were made (This can be done in the [Teardown])

    MockManager.Verify();

}

Natural Mocks™ on the other hand, support recording of expectations:

[TestMethod]

public void Authenticated()

{

    Authentication authenticator = new Authentication();

    // set up our expectations for 2 Log calls in IsAuthenticated

    // 1) “Entering Authentication” Log at first line

    // 2) “User login failed user” Log

    using (RecordExpectations recorder = RecorderManager.StartRecording())

    {

        // CAUTION: ALL calls here are mocked!!!

        Logger.Log(Logger.NORMAL, null); // 1

        Logger.Log(Logger.NORMAL, null); // 2

    }

    // Thats it folks

 

    // authentication should fail

    Assert.IsFalse(authenticator.IsAuthenticated(“user”, “password”));

    // Verify that all calls were made (This can be done in the [Teardown])

    MockManager.Verify();

}

Too bad you can only have this on the Professional and Enterprise versions, but you’ll get other stuff like code coverage and NAnt and MSBuild support.

 

TypeMock doesn’t support mock scopes. Also makes no use of Generics forcing us to a constant use of casts.

TypeMock has support forums in its site and a great e-mail support. And they listen to suggestions (at least to, mine).


This is just my opinion on these mock frameworks and not an extensive analysis of mock frameworks or even the ones mentioned.

8 thoughts on “Unit Testing and Mock Frameworks”

  1. POCMock is a good tool too!
    You can mock anything, events, fields! …
    You can have whatever constraint you want on parameters, supports ref and out parameters mocking…

  2. Suppose my ABC mrthod return 2 out paramters and i want to catch it into my calling method. like mockObj.ExpectAndReturn(“methodname”,,,)

    Please help me in this regard

Comments are closed.