I've been a big fan of Rhino.Mocks for many years, but the original Rhino.Mocks maintainer (Oren Eini aka Ayende) stated in 2013 that he is no longer maintaining the project and has handed the project over to a new maintainer (Mike Meisinger), but Mike has not been actively maintaining the project. It's effectively dead and very unlikely to support future versions of .NET, including .NET core.
Moq (pronounced "Mock") has become the de facto replacement.
This post hopes to serve as a guide for people making the transition from Rhino.Mocks to Moq.
One big difference between Rhino.Mocks and Moq is what gets returned when you generate the mock and how you operate against it. With Rhino.Mocks, the MockRepository returns to you an instance of the type you're mocking and you apply the mock operators (.Stub()
, .Expect()
, .VerifyAllExpectations()
, etc) directly to that mocked object. Moq, on the other hand, creates a wrapper object that contains a reference to the mocked type.
So in this example, I'm creating an mock of IFoo
. For Rhino.Mocks, I get back an IFoo
object, but Moq returns a Mock<IFoo>
and to get the IFoo
object, you access it with the .Object
property.
Rhino.Mocks | Moq |
---|---|
IFoo mock = MockRepository.GenerateMock<IFoo>(); | Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(); IFoo mockedObject = mockWrapper.Object; |
When using Moq, if you have a reference to the mocked object, you can get back to the wrapper object with this helper method: Mock<IFoo> mockWrapper = Mock.Get(mockedObject);
Generating Different Mock Types
For those of you that read my Using Rhino.Mocks Quick Guide, you may recall there are three types of mocks that can be generated by Rhino.Mocks:
- Strict Mock
- A strict mock requires you to provide alternate implementations for each method/property that is used on the mock. If any methods/properties are used which you have not provided implementations for, an exception will be thrown.
- Dynamic Mock
- With a dynamic mock, any methods/properties which are called by your tests for which you have not provided an implementation will return the default value for the data type of the return value. In other words, you'll get back a
0
for number types,false
for Booleans and anull
for any object types. - Partial Mock
- A partial mock will use the underlying object's implementation if you don't provide an alternate implementation. So if you're only wanting to replace some of the functionality (or properties), and keep the rest, you'll want to use this. For example, if you only want to override the method
IsDatabaseActive()
, and leave the rest of the class as-is, you'll want to use a partial mock and only provide an alternate implementation forIsDatabaseActive()
.
Note that Moq uses the term "Loose Mock" for the Dynamic mock concept. Both frameworks default to Dynamic\Loose mocks.
Here's how you generate the same concepts in Moq:
Mock Type | Rhino.Mocks | Moq |
---|---|---|
Strict Mock | IFoo mock = MockRepository.GenerateStrictMock<IFoo>(); | Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(MockBehavior.Strict); |
Dynamic\Loose Mock | IFoo mock = MockRepository.GenerateMock<IFoo>(); | Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(); or Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(MockBehavior.Loose); |
Partial Mock | IFoo mock = MockRepository.GeneratePartialMock<IFoo>(); | Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>() { CallBase = true }; |
I'm not a fan of this syntax, because it lets you mix methods in ways that don't make sense, like a strict mock that calls it's base methods: Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(MockBehavior.Strict) { CallBase = true };
. It's not clear what will happen in this scenario if I call a method I haven't explicitly mocked, because using two different inputs (a constructor argument and a property) to represent competing concepts leads to confusion. That said, I can tell you what happens: The Strict
setting takes precedent and a runtime exception is thrown:
Moq.MockException : Class1.GetFoo() invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.
Passing Constructor Arguments
If you need to pass arguments to the constructor of the class you're trying to mock, there are overloads to allow you to do that.
Rhino.Mocks | Moq |
---|---|
IFoo mock = MockRepository.GenerateMock<IFoo>(param1, param2); | Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(param1, param2); or Mock<IFoo> mockWrapper = new Moq.Mock<IFoo>(MockBehavior.Strict, param1, param2); |
Stubs vs Mocks
Again, from my Using Rhino.Mocks Quick Guide, you may recall that:
A stub is simply an alternate implementation. A mock, however, is more than that. A mock sets up an expectation that
- A specific method will be called
- It will be called with the provided inputs
- It will return the provided results
In Rhino.Mocks, you used the .Stub()
and .Expect()
extension methods to generate your stubs and mocks directly off your mock object. Moq, on the other hand, uses the .Setup()
method on the wrapper object to create both. By default, it will create a stub (no expectation), but if you add Verifiable()
, it will generate the expectations (thus, becoming a mock).
For both frameworks, you can explicitly verify stubs, but if you want to do mass verification, you must create the expectations up front.
For Methods:
Rhino.Mocks | Moq | |
---|---|---|
Stub | mock.Stub(x => x.SomeMethod()).Return(true); | mockWrapper.Setup(x => x.SomeMethod()).Returns(true); |
Mock | mock.Expect(x => x.SomeMethod()).Return(true); | mockWrapper.Setup(x => x.SomeMethod()).Returns(true).Verifiable(); |
Properties are a different story. In Moq, in addition to Mocks that carry expectations, you can generate stubs for properties that basically allow the properties to be set and have them return the values when the getter is called. You can do this for individual properties (and optionally provide an initial value) or you can do it for all properties with a single call using .SetupAllProperties()
.
Rhino.Mocks, on the other hand, doesn't provide the ability to track property values, so to get that same functionality, you'd need to use a callback (.Do()
or .Callback()
) and track the value yourself.
For Properties:
Rhino.Mocks | Moq | |
---|---|---|
Stub (always return same value) | mock.Stub(x => x.SomeProperty).Return(true); | mock.Setup(foo => foo.SomeProperty).Returns("bar"); |
Stub (returns tracked value) | (must use a callback) | mock.SetupProperty(f => f.SomeProperty); |
Stub w/ initial value (returns tracked value) | (must use a callback) | mock.SetupProperty(f => f.SomeProperty, "bar"); |
Mock (always return same value, create expectation) | mock.Expect(x => x.SomeProperty).Return(true); | mock.SetupSet(foo => foo.SomePropertyName).Returns("bar"); mock.SetupGet(foo => foo.SomeProperty) |
Verifying expectations
The concepts here are pretty similar. You can verify individual call patterns, or (if you created a Mock and not a Stub) you can verify all of the expectations you created in a single pass.
For Methods:
Rhino.Mocks | Moq | |
---|---|---|
Called | mock.AssertWasCalled(x => x.SomeMethod()); | mockWrapper.Verify(x => x.SomeMethod()); |
Called a specific number of times | mock.AssertWasCalled(x => x.SomeMethod(), options => options.Repeat.Times(2) ); | mockWrapper.Verify(x => x.SomeMethod(), Times.Exactly(2)); |
Not called | mock.AssertWasNotCalled(x => x.SomeMethod()); | mockWrapper.Verify(x => x.SomeMethod(), Times.Never); |
For Properties
Rhino.Mocks | Moq | |
---|---|---|
Get | mock.AssertWasCalled(x => x.SomeProperty); | mockWrapper.VerifyGet(x => x.SomeProperty); |
Set | mock.AssertWasCalled(x => x.SomeProperty = true); | mockWrapper.VerifySet(x => x.SomeProperty); |
Not called | mock.AssertWasNotCalled(x => x.SomeProperty = true); | mockWrapper.VerifySet(x => { x.SomeProperty = true; }, Times.Never); |
Mass Verification
Moq can do mass verification in two ways. If you have created a mock that sets up expectations using .Expect()
in Rhino.Mocks or .Verifiable()
in Moq, you can use Moq's .Verify()
method to validate just those expectations. Moq also provides a .VerifyAll()
method which will validate all of the mocks and stubs you've created with .Setup()
.
Rhino.Mocks | Moq | |
---|---|---|
Verify Mocks only | mock.VerifyAllExpectations(); | mockWrapper.Verify(); |
Verify Mocks and Stubs | (not available) | mockWrapper.VerifyAll(); |
Controlling Mock Behaviors
Here are some of the general behavior modifications in Rhino.Mocks and their Moq equivalents:
Rhino.Mocks | Moq | |
---|---|---|
Change how many times to use the mock | use .Repeat() : mock.Expect(x => x.SomeProperty) .Repeat.Times(2) .Return(true); | use .SetupSequence() : mockWrapper.SetupSequence(x => x.SomeMethod()) .Returns(true) .Returns(true) .Throws( new Exception("Called too many times")); |
Ignore arguments | use .IgnoreArguments() : mock.Expect(x => x.SomeMethod("param")) .IgnoreArguments() .Return(true); | use argument constraints: mockWrapper.Setup(x => x.SomeMethod(It.IsAny<string>())) .Returns(true); |
Advanced Argument Constraints
Both frameworks provide ways to put advanced constraints on the arguments that trigger a mock. Below are examples -- you'll need to consult the framework documentation for the full list of available constraints.
Rhino.Mocks
mock.Stub(dao => dao.GetRecordFromDatabase(
Arg<int>.Is.GreaterThanOrEqual(0),
Arg<decimal>.Is.NotEqual(2.0),
Arg<List<string>>.List.ContainsAll(new List<string> { "foo", "bar" }),
Arg<object>.Is.NotNull,
Arg<object>.Is.Anything))
.Return(recordFromDatabase);
Moq
mockWrapper.Setup(dao => dao.GetRecordFromDatabase(
It.Is<int>(i => i >= 0),
It.Is<decimal>(d => d != 2.0m),
It.IsRegex("[a-d]+"),
It.IsNotNull<object>(),
It.IsAny<object>()))
.Return(recordFromDatabase);
Providing a Method Implementation / Using the Input Params
For Rhino.Mocks, in order to provide an alternate implementation, you use the .Do()
method to provide a delegate. In Moq, the .Returns()
method has an overload that lets you provide a delegate.
Rhino.Mocks
mock.Stub(dao => dao.GetRecordFromDatabase(0))
.IgnoreArguments()
.Repeat.Any()
.Do((Func<int, ImportantData>)(input => new ImportantData
{
Name = "Orignal Name",
RecordId = input
}));
Moq
mockWrapper.Setup(dao => dao.GetRecordFromDatabase(It.IsAny<int>()))
.Returns((Func<int, ImportantData>)(input => new ImportantData
{
Name = "Orignal Name",
RecordId = input
}));
Throwing an Exception Instead
This is pretty much a drop-in replacement when creating the mock/stub. Where Rhino.Mocks uses .Throw()
for this purpose, Moq uses .Throws()
;
Testing Non-Public Members
With Rhino.Mocks, you can’t mock private or protected members, but you can mock internal members if you add an InternalsVisibleTo
attribute for the Castle dynamic proxy assembly. Moq also uses the same proxy, so you'll still need to add the attribute, but Moq has the added benefit of being able to mock protected members. See the Moq Quickstart Guide for details on how to do this.