Moving from RhinoMocks to Moq

RhinoMocks is a framework for creating mocked instances, that can be used within unit tests. Since the framework is not to be maintained anymore (last version was in 2010), you can’t use RhinoMocks for example within .Net Standard or .Net Core projects.

A project I was working on was having the same struggle; we had quite a large set of unit tests that where using RhinoMocks. For several reasons, we decided to migrate our projects to .Net Core, which made it impossible to use RhinoMocks anymore. We decided to switch to the Moq framework. In this blog I summed up the most used RhinoMocks constructions and how to port them to Moq.

Starting the transition

The easiest way to start the transition from RhinoMocks to Mock is remove per project the reference to the RhinoMocks library and replace it by Moq. When you compile the project then, it will fail to compile. You then “port” each file from RhinoMocks to Moq until the whole library compiles back again.

Mocking an interface

In RhinoMocks you would normally create a mock this way:

ICamera camera = MockRepository.GenerateMock<ICamera>();

In Moq you can transform this in the following way:

var cameraMock = new Mock<ICamera>();

If you want to use the mocked instance, you can refer to it like this:

cameraMock.Object();

While new Mock<ICamera> will return an object of type Mock<ICamera>, the latter one will return an object of type ICamera. This is our mocked instance.

Defining behaviour

When you want your mocked object to return a value, you would in RhinoMocks use the following approach:

ICamera camera = MockRepository.GenerateMock<ICamera>();
camera.Expect(c => c.TakeSnapshot(Arg<bool>.Is.Anything)).Return(true);

In Moq this would look like this:

var cameraMock = new Mock<ICamera>();
cameraMock.Setup(c => c.TakeSnapshot(It.IsAny<bool>()).Returns(true);

Verify that method is called a number of times

Within Moq it seems harder to set the number of times you would expect a method to be called. In RhinoMocks you would for example have this construction:

ICamera camera = MockRepository.GenerateMock<ICamera>();
camera.Expect(c => c.TakeSnapshot(Arg<bool>.Is.Anything)).Return(true).Repeat.Once();

The problem is that Setup within Moq doesn’t have the extension Repeat or something similar. You would need to use Verify within Moq to define it like this (which is not that clean, since you have to duplicate the action you want to verify):

Mock<ICamera> cameraMock = new Mock<ICamera>();
cameraMock.Setup(c => c.TakeSnapshot(It.IsAny<bool>()).Returns(true);

At the end of your test you can verify it like this:

cameraMock.Verify(c => c.TakeSnapshot(It.IsAny<bool>()), Times.Once());

Or a little bit cleaner:

Experssion<Func<ICamera, bool>> takeSnapshotAction = c => c.TakeSnapshot(It.IsAny<bool>());
Mock<ICamera> cameraMock = new Mock<ICamera>();
cameraMock.Setup(takeSnapshotAction).Returns(true);
...
cameraMock.Verify(takeSnapshotAction), Times.Once());

Returning different value after method is called again

Within Moq to define a diffent value, when for example a method is called the second time, you use MockSequence.

var sequece = new MockSequence();
Mock<ICamera> cameraMock = new Mock<ICamera>();
cameraMock.InSequence(sequence).Setup(c => c.TakeSnapshot(It.IsAny<bool>())).Returns(true);
cameraMock.InSequence(sequence).Setup(c => c.TakeSnapshot(It.IsAny<bool>())).Returns(false);

So, when the first time TakeSnapshot is called on our mock, true will be returned. The second time when the method is called again, false will be returned.

Conclusion

If you use the AAA test approach, it is quite easy to convert unit tests using Rhino Mocks to Moq. Most of the functionality that is available in RhinoMocks exists in Moq, although different constructions are needed.

Moq is, compared to RhinoMocks, a framework that is still being maintained and extended. This will minimize issues you might run into when using newer .Net Frameworks.

What both frameworks however lack is good documentation with examples. The only thing I could find regarding Moq is a quickstart manual and API documentation. However, this is still better with the quite concise documentation of RhinoMocks.

Posted in C#, TDD, Unit testing by Bruno at June 29th, 2020.

Leave a Reply