TypeMocks™ 4.0.0 is now available

TypeMocks™ 4.0.0 is now available.

In my previous analysis mentioned two drwanbacks of this mocking framework:

  1. The lack of a mocking scope.
  2. The lack of the use of Generics in its APIs.

Let’s start with the second one.

Generic Reflective API

TypeMocks™ was the same tool for both the .NET 1.1 and the .NET 2.0 runtimes and they were avoiding the need to have two tools. But we already need two runtimes and two IDEs, so two versions of TypeMocks™ isn’t such an hassle. I’m glad they came to their senses about this.

Befere this new API, the usage of mocks was something like this:

MockObject mockObject = MockManager.MockObject(typeof(IIdentity));

mockObject.ExpectGetAlways(“Name”, “username”);

IIdentity identity = (IIdentity)(mockObject.Object);

Now, it’s more like this:

MockObject<IIdentity> mockObject = MockManager.MockObject<IIdentity>();

mockObject.ExpectGetAlways(“Name”, “username”);

IIdentity identity = mockObject.Object;

You’ll have to agree with me that the changes in lines 1 and 3 improve the reliability and readability of the test code.

Mocking Scope

The need for this one may not be obvious, so let’s look at an example.

Imagine we are testing this class:

public class TestedClass

{

    string value;

 

    public TestedClass(bool create)

    {

        if (create)

        {

            this.value = new ClassUsedByTestedClass().Value;

        }

    }

 

    public string Value

    {

        get

        {

            return this.value;

        }

    }

}

As you can see, TestedClass uses ClassUsedByTestedClass:

public class ClassUsedByTestedClass

{

    public ClassUsedByTestedClass()

    {

        throw new NotImplementedException();

    }

 

    public string Value

    {

        get

        {

            throw new NotImplementedException();

        }

    }

}

Now, take these two tests:

[TestMethod()]

public void TestMethod1()

{

    const string mockedValue = “mocked value”;

    const bool create = false;

 

    using (RecordExpectations recorder = RecorderManager.StartRecording())

    {

        ClassUsedByTestedClass c = new ClassUsedByTestedClass();

        string v = c.Value;

        recorder.Return(mockedValue);

    }

 

    TestedClass t = new TestedClass(create);

 

    Assert.AreEqual(mockedValue, t.Value);

}

 

[TestMethod()]

[ExpectedException(typeof(NotImplementedException))]

public void TestMethod2()

{

    const bool create = true;

 

    TestedClass t = new TestedClass(create);

}

These two tests will fail because the value of create in test one is wrong. To shield ourselves from this kind of mistakes, we can code the tests this way:

[TestMethod()]

public void TestMethod1()

{

    MockManager.ClearAll();

 

    const string mockedValue = “mocked value”;

    const bool create = false;

 

    using (RecordExpectations recorder = RecorderManager.StartRecording())

    {

        ClassUsedByTestedClass c = new ClassUsedByTestedClass();

        string v = c.Value;

        recorder.Return(mockedValue);

    }

 

    TestedClass t = new TestedClass(create);

 

    Assert.AreEqual(mockedValue, t.Value);

 

    MockManager.Verify();

}

 

[TestMethod()]

[ExpectedException(typeof(NotImplementedException))]

public void TestMethod2()

{

    MockManager.ClearAll();

 

    const bool create = true;

 

    TestedClass t = new TestedClass(create);

 

    MockManager.Verify();

}

Now it’s clear that the wrong test is the first one. But I like to scope things using the using statement, so, this is a better looking solution.

[TestMethod()]

public void TestMethod1()

{

    using (new MockScope())

    {

        const string mockedValue = “mocked value”;

        const bool create = false;

 

        using (RecordExpectations recorder = RecorderManager.StartRecording())

        {

            ClassUsedByTestedClass c = new ClassUsedByTestedClass();

            string v = c.Value;

            recorder.Return(mockedValue);

        }

 

        TestedClass t = new TestedClass(create);

 

        Assert.AreEqual(mockedValue, t.Value);

    }

}

 

[TestMethod()]

[ExpectedException(typeof(NotImplementedException))]

public void TestMethod2()

{

    using (new MockScope())

    {

        const bool create = true;

 

        TestedClass t = new TestedClass(create);

    }

}

I would be very happy with this last solution. But both these two solutions have have too much mocking infrastruture coded in the test code and, because the people at TypeMocks™ aren’t in the market of just making me happy, they came up with a better solution (available on Professional and Enterprise Editions only):

[TestMethod()]

[VerifyMocks]

public void TestMethod1()

{

    const string mockedValue = “mocked value”;

    const bool create = false;

 

    using (RecordExpectations recorder = RecorderManager.StartRecording())

    {

        ClassUsedByTestedClass c = new ClassUsedByTestedClass();

        string v = c.Value;

        recorder.Return(mockedValue);

    }

 

    TestedClass t = new TestedClass(create);

 

    Assert.AreEqual(mockedValue, t.Value);

}

 

[TestMethod()]

[ExpectedException(typeof(NotImplementedException))]

[VerifyMocks]

public void TestMethod2()

{

    const bool create = true;

 

    TestedClass t = new TestedClass(create);

}

And do you know what they called this? Best Practices Patterns.

Generic Test Decorator

TypeMocks™ is more than just a mocking framework, and it now enables writing custom test decorators. These are test framework agnostic and it is simple to add more features to your tests. Now you can write your own version of VerifyMocksAttribute and ClearMocksAttribute (available on Enterprise Edidion only).

Mock Signed Internal Interfaces

It’s now possible to mock internal interfaces in signed assemblies.

Enhancements to Natural TypeMocks™

It is now possible to create return values within the recording block, saving even more time and having an easier flow.

Before you had to do this:

DateTime d = new DateTime(2007, 5, 20);

using (RecordExpectations recorder = RecorderManager.StartRecording())

{

    TestedClass mc = new TestedClass(new DateTime());

    DateTime v = mc.Value;

    recorder.Return(d);

}

Now you can just do this:

using (RecordExpectations recorder = RecorderManager.StartRecording())

{

    TestedClass mc = new TestedClass(new DateTime());

    DateTime v = mc.Value;

    recorder.Return(new DateTime(2007, 5, 20));

}

There’s also a ReturnDefaultImplementation method in the RecordExpectations class that returns a mock that has default behavior.

.. and several other enhancements and bug fixes.