Replacing Typemock Fakes With Moq Mocks

2021-01-04 7 min read Code Example David Poxon

Recently, I had the pleasure of migrating some complex tests from TypeMock to Moq. I learned a lot in the process, and wanted to capture my learnings for others. This article is the first in a series I will be writing on migrating from TypeMock’s C# implementation to Moq. In this article I will discuss replacing TypeMock’s ‘fakes’ with Moq’s ‘mocks’.

First, some background. TypeMock and Moq are both object mocking frameworks, i.e., they enable the creation of mock object representations of complex objects. Mocks are used to mimic, or force, the behaviour of real objects for testing purposes. However, TypeMock and Moq have distinct approaches to creating mock objects; the most important distinction is around mocking instance members, e.g., methods. TypeMock uses some extremely deep magic to intercept method calls as they’re about to occur and redirect execution to the ‘mocked’ method. This gives users of TypeMock the ability to generally mock objects of any class (there are exceptions, e..g, only a subset of Microsoft’s mscorlib types are mockable) and any of their members, e.g., methods. This includes private members. In contrast, Moq uses code generation to mock objects; meaning that Moq can only mock methods that are implementable, i.e., public virtual or abstract methods, or interface methods. So, TypeMock is by far the more powerful framework. However, this power comes with a great cost: as TypeMock can generally mock anything, users can avoid some of the better design principles, with inversion of control, i.e., dependency injection, being top of the list.

The examples that follow will assume that the testing project using TypeMock uses TypeMock to it’s fullest extent, i.e., avoiding inversion of control. In our Moq examples we will present how to replace ‘fakes’ with ‘mocks’ from both the perspective of the required syntactic changes and the perspective of introducing inversion of control to the classes we wish to test.

tl;dr;: I’m going to present syntax and design principles to migrate from TypeMock to Moq.

In this post I will discuss two mocking scenarios:

  • mocking passed instances, i.e., where we control instance creation; and
  • mocking hidden instances, i.e., where we don’t control instance creation.

Mocking Passed Instances

First, let’s discuss the simpler scenario: passing a mocked object. In the following example program, we have a class Person who has a Dog who is their best friend. Each instance of Dog has a method that enables them to be pat. Each Person has a defined method for patting their best friend PatBestFriend. We want to write a test that when the person is told to pat their best friend that they do, in fact, pat their best friend.

Here is the defined program:

namespace Program
{
    public class Person
    {
        private Dog bestFriend;

		public Person(Dog bestFriend)
		{
			this.bestFriend = bestFriend;
		}

		public void PatBestFriend()
		{
			bestFriend.Pat();
		}
    }

    public class Dog
	{
		public void Pat()
		{
			// is patted
		}
	}
}

Below is our TypeMock-based test for ensuring that the person does the right thing and pats their best friend. The test creates a fake instance of Dog using Isolate.Fake.Instance<Dog>(), and passes this fake instance to an instance of Person. We then tell the instance of person to pat the dog. Finally, using Isolate.Verify.WasCalledWithAnyArguments(() => fakeDog.Pat()) we verify that the person did what we asked by checking that the .Pat() method was called on our fake Dog.

using Program;
using TypeMock.ArrangeActAssert;
using Xunit;

namespace ProgramUnitTests
{
    public class PersonUnitTests
    {
        [Fact, Isolated]
        public void PatBestFriend()
		{
			// Arrange
			var fakeDog = Isolate.Fake.Instance<Dog>();
			var person = new Person(fakeDog);

			// Act
			person.PatBestFriend();

			// Assert
			Isolate
                .Verify
                .WasCalledWithAnyArguments(() => fakeDog.Pat());
		}
    }
}

Note how in the TypeMock test we are able to create a mock instance of Dog and also mock the behaviour of its member Pat(). Not only is this not possible in Moq, our Person class is highly-dependent on the Dog class and its implementation. To be able to test our Person class using Moq, we are going to need to make some improvements to our production code so that a Person instance doesn’t care what kind of dog it has. This will:

  • make instances of Person more flexible in the face of future code changes, e.g., maybe we introduce more than one type of Dog which respond differently to being pat;
  • improve our ability to test our Person class.

First, our better more testable program, which replaces the reliance on an instance of the concrete type Dog by Person with reliance on an instance of interface type IDog:

namespace Program
{
    public class Person
    {
        private readonly IDog bestFriend;

		public Person(IDog bestFriend)
		{
			this.bestFriend = bestFriend;
		}

		public void PatBestFriend()
		{
			bestFriend.Pat();
		}
    }

    public interface IDog
	{
		void Pat();
	}
}

Now, when we test Person using Moq, we can use a mocked instance of type IDog:

using Moq;
using Program;
using Xunit;

namespace ProgramUnitTests
{
    public class PersonUnitTests
    {
        [Fact, Isolated]
        public void PatBestFriend()
		{
			// Arrange
			var fakeDog = new Mock<IDog>();
			var person = new Person(fakeDog);

			// Act
			person.PatBestFriend();

			// Assert
            fakeDog.Verify(x => x.Pat(), Times.AtLeastOnce);
		}
    }
}

Also note the updated syntax:

  • rather than creating a mocked object using Isolate.Fake.Instance<Dog>() we now use Mock<IDog>(); and
  • instead of verifying .Pat() was called using Isolate.Verify.WasCalledWithAnyArguments(() => fakeDog.Pat()) we instead use fakeDog.Verify(x => x.Pat(), Times.AtLeastOnce).

Mocking Hidden Instances

Let us now consider the more complex scenario: creating a mocked object when creation is out of our control. We start with a slightly modified version of our original example. In the original example we passed an instance of Dog when creating a person; in our updated example, we create the Dog instance when we create the Person instance.

Here is the defined program:

namespace Program
{
    public class Person
    {
        private Dog bestFriend;

		public Person()
		{
			bestFriend = new Dog();
		}

		public void PatBestFriend()
		{
			bestFriend.Pat();
		}
    }

    public class Dog
	{
		public void Pat()
		{
			// is patted
		}
	}
}

Below is one approach to testing .PatBestFriend() using TypeMock. In the TypeMock tests for the previous example, we faked an instance of Dog. In this example, we’re asking TypeMock to fake the next instance of Dog to be created. This means that when our instance of Person creates a new Dog instance, the Dog instance will be a TypeMock fake.

using Program;
using TypeMock.ArrangeActAssert;
using Xunit;

namespace ProgramUnitTests
{
    public class PersonUnitTests
    {
        [Fact, Isolated]
        public void PatBestFriend()
		{
			// Arrange
			var fakeDog = Isolate.Fake.NextInstance<Dog>();
			var person = new Person();

			// Act
			person.PatBestFriend();

			// Assert
			Isolate
                .Verify
                .WasCalledWithAnyArguments(() => fakeDog.Pat());
		}
    }
}

Again, Moq simply doesn’t have the power to intercept the creation of concrete instances like TypeMock. Luckily. This limitation in Moq is going to force us to refactor our code to make it more testable. To do this, we’re going to build on our previous update using IDog to inject a factory for instances of IDog. This factory is what will be used by the Person instance to create instances of IDog. In our tests, we’ll pass in a factory for making mocked instances of IDog. Below is the improved, more testable program:

namespace Program
{
    public class Person
    {
        private readonly IDog bestFriend;

		public Person(IDogFactory bestFriendFactory)
		{
			bestFriend = bestFriendFactory.Create();
		}

		public void PatBestFriend()
		{
			bestFriend.Pat();
		}
    }

   public interface IDog
    {
        void Pat();
    }

    public interface IDogFactory
    {
        IDog Create();
    }
}

Now, when we write our test, we inject into Person instance a factory for making mocked instances of IDog:

using Moq;
using Program;
using Xunit;

namespace ProgramUnitTests
{
    public class PersonUnitTests
    {
        [Fact]
        public void PatBestFiend()
        {
            // Arrange
            var mockDogFactory = new MockDogFactory();
            var person = new Person(mockDogFactory);

            // Act
            person.PatBestFriend();

            // Assert
            mockDogFactory
                .DogMock
                .Verify(x => x.Pat(), Times.AtLeastOnce);
        }
    }

    public class MockDogFactory : IDogFactory
    {
        public Mock<IDog> DogMock;

        public IDog Create()
        {
            var mock = new Mock<IDog>();
            DogMock = mock;
            return mock.Object;
        }
    }
}

Note that in the implementation for MockDogFactory.Create(), we store our instance of Mock<IDog> in DogMock. Calling new Mock<IDog>() creates a new mock object, and its property .Object provides access to the mocked object. To verify that the .Pat() method was called, we have to call a method on the mock object, rather than the mocked object, and this is why we store it for later retrieval.

Also, note that this approach also works in scenarios where TypeMock’s AllInstances is used, e.g., Isolate.Fake.AllInstances<Dog>().

Summary

In this post we have presented two scenarios in which TypeMock fakes are used and provided Moq-based alternatives. These scenarios cover when the creation of the object to fake is:

  • in control of the method caller; and
  • not in the control of the method caller.

More in this series on replacing Typemock with Moq:

comments powered by Disqus