Mocking frameworks can be 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. There are many different mocking frameworks available for use in .Net, each with their own variations on syntax and approach. There are two main categories of mocking frameworks, Constrained and Unconstrained, and I describe how each works in my post How .Net Mocking Frameworks Work Under the Hood.
This post is broken into several sections, starting with a general overview and then hitting on several specific use cases of interest:
- Mock Options
- Stubs vs Mocks
- Using Mocks to Limit the Scope of Your Tests
- General Framework Usage
- Creating a Mock
- Controlling Mock Behaviors
- Change How Many Times to Use the Mock
- Returning Prepared Values Based on the Input Values
- Returning the Prepared Values Regardless of the Input Values
- Advanced Argument Constraints
- Providing a Method Implementation / Using the Input Params
- Mocking Things Other Than Methods
- Throwing an Exception Instead
- Testing Non-Public Members
Mock Options
Most .Net mocking frameworks support 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 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()
. (This type of mock is not valid for interfaces.)
IMPORTANT: Constrained mocking frameworks can only mock/stub virtual or abstract 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. (See my post How .Net Mocking Frameworks Work Under the Hood for more details.)
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
The distinction between the two has lead to a fair amount of confusion over time, so not all frameworks differenciate between the two, and even some that do (like RhinoMocks) blur the lines a bit. Some framework have choosen to only support Mocks in order to reduce confusion. Some give them differnt names, such as "Fakes", "Substitute", or "Shim".
In addition to setting up an alternate behavior for when the code is run, the frameworks also provide a mechanism for verifying members were/were not called during execution. For example, RhinoMocks provides a .VerifyAllExpectations()
method to ensure all Mocks were called, as well as .AssertWasCalled(...)
and .AssertWasNotCalled(...)
methods to validate specific members were/were not used during the exectution.
Since mocking frameworks are intended for use within unit testing frameworks, Exceptions are used to signal when your code has violated the expectations. For instance, if you've created a strict mock and your code attempts to use a method that hasn't been specifically mocked, an exception will be thrown. Or, if you utilize one of the post-execution validation methods to check if a member was/wasn't used, an exception will be thrown if your expectations weren't met.
For example, the below test using RhinoMocks will fail due to an ExpectationViolationException
being thrown since Expect(101)
is not being called.
[Test]
public void TestExpectations()
{
//Arrange
int myRecordId = 100;
var recordFromDatabase = new ImportantData
{
Name = "Orignal Name",
RecordId = myRecordId
};
var mockDAO = MockRepository.GenerateMock<IDataAccess>();
mockDAO.Expect(dao => dao.GetRecordFromDatabase(101))
.Return(recordFromDatabase);
var fancyBL = new FancyBusinessLogic { MyDataAccessObject = mockDAO };
//Act
fancyBL.GetImportantDataAndUpdateTheName(myRecordId);
//Assert
mockDAO.VerifyAllExpectations();
}
Using Mocks to Limit the Scope of Your Tests
Let's say I have a class that I want to test, but it relies on a database object to fetch/update, etc records from the database. I want to test my class in isolation from the database, so I mock the database object's interface, which allows me to control the flow of information within my implementation.
To achieve this in the code sample below, I generate a stub for the database object'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 database layer (which is not even used since I'm mocking an Interface) and ensures my test is controlling the inputs and outputs so I'm getting exactly what I want for my specific test condition.
[Test]
public void TestGetImportantDataAndUpdateTheName()
{
//Arrange
int myRecordId = 100;
var recordFromDatabase = new ImportantData {RecordId = myRecordId};
var mockDAO = MockRepository.GenerateMock<IDataAccess>();
mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
.Return(recordFromDatabase);
var objectUnderTest = new FancyBusinessLogic { MyDataAccessObject = mockDAO };
//Act
var myRecord = objectUnderTest.GetImportantDataAndUpdateTheName(myRecordId);
//Assert
Assert.AreEqual(myRecord.RecordId, myRecordId);
Assert.AreEqual(myRecord.Name, "All Your Base Are Belong To Us");
}
General Framework Usage
Each framework has it's own syntax, so for this guide I'm covering the concepts but can't give specific since they variy widely. I've created a few framework-specific pages to help with the syntax of some of the more populate frameworks:
- Using Rhino.Mocks - quick guide to generating mocks and stubs
- A Guide to Moq for Rhino.Mocks Users
- A Guide to NSubstitute for Rhino.Mocks Users
Creating a Mock
To generate mocks, you'll genearlly use a static factory to create the specific type of mock you want (strict, dynamic or partial). There are typically generic methods such as the following (from RhinoMocks):
GenerateMock<T>
(for DynamicMocks)GeneratePartialMock<T>
GenerateStrictMock<T>
where the T is the class/interface being mocked. Some frameworks will allow you differenciate between mocks and stubs at this time as well, but most do that on a member-by-member basis. The contructor parameters, if you need to provide any, will generally be passed as parameters to this factory method.
For some frameworks the return type directly implements the type you're mocking and the configuration of the mock (see below) is done via extention methods off that type. In other cases, such as Moq, the type returned is a specific type defined by the framework and the actual mocked type is a property on that object. For example, in the case of Moq, you have to use mock.Object
to access the mock itself.
Controlling Mock Behaviors
In this section, I'll describe some of the basic things you can do to configure mocks and stubs that are available in all the mocking frameworks. Some frameworks, particularly the Unconstrained types, provide addition functionality beyone these, so make sure to get up to speed on the specific framework you've selected.
Almost all frameworks you a fluent-style builder pattern when configuring your mocks. This means you chain a set of method calls together to build out how you want the mock to work.
First and foremost, for frameworks that differenciate between mocks and stubs, you will need to start your configuration by stating if it's a mock or a stub (see the "Mocks vs Stubs" section above for the difference). Usually that with a .Mock(...)
, Expect(...)
or .Stub(...)
method, but the names vary greatly. Frameworks that don't differenciate between mocks and stubs will have a Setup(...)
, or Fake(...)
method. The parameter to these methods is generally a delegate/lambda express for the member being mocked, like this: mock.Stub(x => x.MyFavoriteMethod())
.
The primary configuration you'll provide for a mock is the return value. This is usually done via a method named Return(...)
, to which you provide the value you want returned from the mocked implementation. For example: mock.Mock(x => MyFavoriteMethod()).Return(false)
.
Change How Many Times to Use the Mock
Once you've setup the mock, you can change how many times it applies in the event your code calls the mocked member more than once. For many, but not all, frameworks, setting up a mock will 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, so the frameworks provide mechanisms to adjust how many times the mock should be used. Note that with a mock, you're potentially setting up expectations for how many times it will be called.
In most frameworks, there's some sort of "Repeat" option you can use, such as these from RhinoMocks: .Repeat.Any()
, .Repeat.Once()
, .Repeat.Times(10)
.
mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
.Repeat.Any()
.Return(recordFromDatabase);
You may also have a Repeat.Never()
option, which will set the expectation the member is never called.
Returning Prepared Values Based on the Input Values
When setting up a mock or stub for a method that takes parameters, the default behavior is to only trigger the mocked behavior when the input exactly match the input you used when configuring the mock. So if you define the mock like this: mockDAO.Stub(dao => dao.GetRecordFromDatabase(100)).Return(null)
, then this mock will only be used when the input value is 100
. All other values will act as if the mock was not configured.
This allows you to have different mocked behanviors based on different inputs. So input 100
could return a valid record, while input 200
would return null
or throw an exception.
Returning the Prepared Values Regardless of the Input Values
Sometimes you want a mock to apply regaurdless of the input values, and the frameworks provide various mechanisms to do that. The typical case is for you to provide something in the method when defining the mock (so that it knows which method overload you want to mock) and then apply a modifier like .IgnoreArguments()
. This will apply the mock for any input.
mockDAO.Stub(dao => dao.GetRecordFromDatabase(myRecordId))
.IgnoreArguments()
.Return(recordFromDatabase);
Advanced Argument Constraints
Other times you don't want to be so all-or-none in your configurations, so all of the frameworks provide ways to be much more granular in your argument matching configurations, allowing you to provide very detailed conditions for when to use your return values by defining per-parameter constraints. For example, here I've used RhinoMocks syntax to stipulate any input greater than 0 should use this stub.
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);
Many frameworks allow you to provide a delegate that gets called and returns true/false as to if the parameter meet the critera for the mock. This allows you to maintain your own state and get very complex in your handling. Beware: The more complex you get, the more difficult it is for future maintainers to understand what you're attempting to test and is a codesmall that maybe your code is doing too much and should be simplified.
Providing a Method Implementation / Using the Input Params
Instead of just providing a simple value to return, you can provide a full implementation of the method, typically as a delegate/lambda function. 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, such as this example using RhinoMock's .Do(...)
syntax:
mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
.IgnoreArguments()
.Do((Func<int, ImportantData>)(input => new ImportantData{RecordId = input}));
Mocking Things Other Than Methods
You're not restricted to just mocking methods. You can mock properties (both getters and setters, though the setter syntax is generally not as straight forward) and events. Some Unconstrained frameworks may also allow you mock constructors, as well as static members of classes.
Throwing an Exception Instead
Instead of returning a value, you can use instruct the mock to force an exception, usually with a .Throw(...)
method, like this:
mockDAO.Stub(dao => dao.GetRecordFromDatabase(0))
.IgnoreArguments()
.Repeat.Any()
.Throw(new NullReferenceException());
Testing Non-Public Members
With Constrained frameworks, you can't mock private or protected members, but you can mock internal members if you do a little extra work.
Most of the popular open-source constrained frameworks utilize Castle DynamicProxy to generate an assembly at runtime with the mock logic (see my post How .Net Mocking Frameworks Work Under the Hood for more details). Specifically, you must allow your test assembly and the proxy 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 Castles' 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")]
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 Constrained frameworks.