Using Rhino.Mocks - quick guide to generating mocks and stubs

This post is a general review of the Rhino.Mocks syntax. While it is intended primarily as a quick reference for myself, I hope anyone who stumbles upon it can also find it useful.

Rhino.Mocks is a .Net mocking framework which is extremely useful for stubbing out objects in your unit tests to ensure you're only testing what you want to test and to allow you to control the environment/state/surroundings under which your tests execute. It is written by Ayende Rahien, the same guy that created nHibernate.  My typical dev unit testing environment would be Visual Studio (C#) + nUnit + Rhino.Mocks. You can either use the nUnit command line tools to run the tests or several good tools that integrate into Visual Studio, such as ReSharper, TestRunner.Net or, my favorite, NCrunch.

For readability, I suggest writing your tests using the Arrange, Act, Assert syntax.

This post is broken into several sections, starting with a general overview and then hitting on several specific use cases of interest:

  • Mock Options
  • Creating a Mock
  • Limiting the Scope of Your Tests
  • Stubs vs Mocks
  • Controlling Mock Behaviors
  • Providing a Method Implementation / Using the Input Params
  • Throwing an Exception Instead
  • Mocking a Property
  • Testing Non-Public Members

The full code for the snippets used in my examples can be found at the end of this posting.

You may also be interested in my posting about Mocking Objects with Restricted Access (internal/private), which has examples of using reflection to manipulate objects that can’t be mocked with Rhino.Mocks.

For additional features, such as raising events in your mock, see the official Rhino.Mocks guide.

Mock Options

Rhino.Mocks supports three basic types of mock objects:

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 a null 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 for IsDatabaseActive().

IMPORTANT: Rhino.Mocks can only mock/stub virtual members of a real class, so make sure the members you care about are virtual -- OR, event better, mock/stub an Interface, in which case you can do whatever you want.

There are also methods for generating Stubs (see “Mocks vs Stubs” section below).

Creating a Mock

To generate mocks, you'll use the static factory Rhino.Mocks.MockRepository. From this factory, you'll create your mock using one of a few generic methods:

  • GenerateMock<T> (for DynamicMocks)
  • GeneratePartialMock<T>
  • GenerateStrictMock<T>

where the T is the class/interface being mocked. The method parameters, if you provide any, will be passed to the object's constructor.

For example:

        var _mockDAO = MockRepository.GenerateMock<IDataAccess>();
        var _mockManager = MockRepository.GenerateStrictMock<IDataManager>(someParam);

As a general rule, I will generate all of my mocks in the test suite [SetUp] method to ensure everything is reset from one test to the next.  You'll see in my test fixture file in the Code Used In Examples section that I have done just that.

Limiting the Scope of Your Tests

Scenario:

I have a BLL object that I want to test, but it relies on a DAL object to fetch/update, etc records from the database. I want to test my BLL object in isolation from the DAL object, so I mock the DAL interface.  

Things to note in this example: I generate a stub for the dao's GetRecordFromDatabase() method so that when it's called with the recordId I care about, it will return my prepared value. This removes the dependency on the DAO layer (which is not even used since I'm mocking an Interface for the DAO) and ensures my test is controlling the inputs and outputs so I'm getting exactly what I want for my specific test condition.

            mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
                   .Return(recordFromDatabase);

Code:


    [Test]
    public void TestGetImportantDataAndUpdateTheName()
    {
        //Arrange
        int myRecordId = 100;
        var recordFromDatabase = new ImportantData
                                     {
                                         Name = "Orignal Name",
                                         RecordId = myRecordId
                                     };

        _mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
                .Return(recordFromDatabase);

        //Act
        var myRecord = _fancyBL.GetImportantDataAndUpdateTheName(myRecordId);

        //Assert
        Assert.AreEqual(myRecord.RecordId, myRecordId);
        Assert.AreEqual(myRecord.Name, "All Your Base Are Belong To Us");
    }

Stubs vs Mocks

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

So when you setup a mock, you use the syntax .Expect() instead of .Stub().  Then, in your asserts, you can do .VerifyAllExpectations() on your mock to ensure reality matched your expectations.

In this example, the test will fail due to an ExpectationViolationException being thrown due to the Expect(101) not being called.


    [Test]
    public void TestExpectations()
    {
        //Arrange
        int myRecordId = 100;
        var recordFromDatabase = new ImportantData
                                     {
                                         Name = "Orignal Name",
                                         RecordId = myRecordId
                                     };

        _mockDAO.Expect(dao => dao.GetRecordFromDatabase(myRecordId))
                .Return(recordFromDatabase);

        _mockDAO.Expect(dao => dao.GetRecordFromDatabase(101))
                .Return(recordFromDatabase);

        //Act
        _fancyBL.GetImportantDataAndUpdateTheName(myRecordId);

        //Assert
        _mockDAO.VerifyAllExpectations();
    }

Update: see my post for more on VerifyAllExpectations vs AssertWasCalled methodsUpdate: found a posting that I think does a good, simple explanation of Mock vs Stub, including a graphic!

Controlling Mock Behaviors

In the above example, I did _mockDAO.Stub().Return().  This will cause the mock object to return the provided value the first time it's called with the provided inputs.  Sometimes we want to change this behavior, thus the following modifiers can be used between the .Stub() and .Return() calls.

Change how many times to use the stub:

Using the .Repeat.Any(), .Repeat.Once(), .Repeat.Times(10) modifiers:

     _mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
             .Repeat.Any()
             .Return(recordFromDatabase);

Return the prepared value regardless of the input value:

Using .IgnoreArguments():

  _mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
          .IgnoreArguments()
          .Return(recordFromDatabase);

Advanced Argument Constraints:

You can provide very detailed conditions for when to use your return values by defining per-parameter constraints. For example, here I've said the input must be greater than 0.

       _mockDAO.Stub(dao => dao.GetRecordFromDatabase(Arg<int>.Is.GreaterThanOrEqual(0)))
               .Return(recordFromDatabase);

Here's an example with more than one parameter: (There's a lot more than this – IntelliSense is your friend)


_mockDAO.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);

Additionally, you can put constraints on properties of objects used as parameters. For instance, if the input parameter had a bool property "IsSomethingICareAbout" and you only wanted to provide a return value when that property is true, you could do this:

            _mockDAO.Stub(x => x.SomeMethod(myObject))
                    .Constraints(Property.Value("IsSomethingICareAbout", true)
                    .Return("foo");

You can put constraints on the input arguments in the same way:


            _mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
                    .Constraints(Is.GreaterThanOrEqual(0))
                    .Return(recordFromDatabase);

And constraints can be chained with boolean operators:


            _mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
                    .Constraints(Is.GreaterThanOrEqual(0) && Is.LessThanOrEqual(100) )
                    .Return(recordFromDatabase);

Note: Constraints must be listed in the order of the parameters (ie: the first set of constraints applies to the first parameter, the second set to the second param, and so on).  And a constraint must be provided for each parameter (you can do Is.Anything() as well).

Providing a Method Implementation / Using the Input Params

Instead of using a .Return() with a simple value, you can provide a full implementation of the method using the .Do() method. This also allows you to get access to the input parameters.  If you want, you can define a delegate and just call the delegate.  I prefer to use lamdas unless the method is really long.

So instead of my previous stub for GetRecordForDatabase which pre-configured a return value, I can do it on the fly:

_mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
                .IgnoreArguments()
                .Repeat.Any()
                .Do((Func<int, ImportantData>)(input => new ImportantData
                                                            {
                                                                Name = "Orignal Name",
                                                                RecordId = input
                                                            }));

Mocking A Property

If you need to mock a property instead of a method, the syntax is pretty much the same:

    [Test]
    public void TestProperty()
    {
        var mockedInterface = MockRepository.GenerateMock<IHasAProperty>();
        mockedInterface.Expect(x => x.StringProperty).Return("fooString");
        Assert.That(mockedInterface.StringProperty, Is.EqualTo("fooString"));
    }

Throwing an Exception Instead

Instead of .Return(), you can use .Throw() to force an exception:


    [Test, ExpectedException(typeof(NullReferenceException))]
    public void TestNeverCallThisMethod2()
    {
        //Arrange
        _mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
                .IgnoreArguments()
                .Repeat.Any()
                .Throw(new NullReferenceException());
               
        object inputValue = null;

        //Act
        _fancyBL.NullsNotWelcomeHere(inputValue);

        //Assert
        //nothing to do here -- ExpectedException
    }

Testing Non-Public Members

With Rhino.Mocks, you can't mock private or protected members, but you can mock internal members if you do a little extra work.

Specifically, you must allow your test assembly to access internal members of the assembly under test.  This means adding two InternalsVisibleToAttributes to the AssemblyInfo.cs file of the assembly under test: one for the unit test assembly and one for Rhino.Mocks' DynamicProxyGenAssembly2.  If you're using signed assemblies, you must put the full public key in the attribute.

You can get the public key for an assembly by using the sn -Tp yourAssembly.dll command in the Visual Studio Command Prompt.

For example: (no wrapping -- can't be any spaces in the public key)

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
[assembly: InternalsVisibleTo("jwright.Blog.UnitTesting, PublicKey=00……ec")]

Code Used In Examples

Here are the full code files to use in order to run my example tests:

DataAccessObject.cs

using System;

namespace jwright.Blog
{
    public class ImportantData
    {
        public string Name { get; set; }
        public int RecordId { get; set; }
    }

    public interface IDataAccess
    {
        ImportantData GetRecordFromDatabase(int recordId);
        void NeverCallThisMethod();
    }

    public class DataAccessObject : IDataAccess
    {
        public ImportantData GetRecordFromDatabase(int recordId) 
                                          { throw new NotImplementedException(); }
        public void NeverCallThisMethod() { throw new NotImplementedException(); }
    }

}

FancyBusinessLogic.cs

namespace jwright.Blog
{
    internal class FancyBusinessLogic
    {
        private IDataAccess _dataAccessObject;
        internal IDataAccess MyDataAccessObject
        {
            get { return _dataAccessObject ?? (_dataAccessObject = new DataAccessObject()); }
            set { _dataAccessObject = value; }
        }

        public ImportantData GetImportantDataAndUpdateTheName(int recordId)
        {
            var record = MyDataAccessObject.GetRecordFromDatabase(recordId);
            record.Name = "All Your Base Are Belong To Us";
            return record;
        }

        public void NullsNotWelcomeHere(object input)
        {
            if (input == null) { MyDataAccessObject.NeverCallThisMethod(); }
        }

    }
}

FancyBusinessLogicTest.cs

using System;
using NUnit.Framework;
using Rhino.Mocks;

namespace jwright.Blog
{
    [TestFixture]
    public class FancyBusinessLogicTest
    {
        private IDataAccess _mockDAO;
        private FancyBusinessLogic _fancyBL;

        [SetUp]
        public void SetUp()
        {
            //reset all my objects under test and mocks
            _mockDAO = MockRepository.GenerateMock<IDataAccess>();
            _fancyBL = new FancyBusinessLogic {MyDataAccessObject = _mockDAO};
        }

        //-----
        // Tests will go here
        //-----
    }
}