Introduction
Microsoft Moles (commonly bundled with Pex) is a stubbing/mocking platform for writing unit tests and keeping your code under test in isolation. Pex and Moles are going away with Visual Studio 2012, to be replaced by Microsoft Fakes. However, if you're like me you might be stuck with VS2010 for a while, or maybe you have your own reason for using Moles.
I personally found the documentation provided for Moles to be frustrating and a lack of examples on the internet didn't help. This article will provide some background on Moles, and will delve specifically into how to create a stub and a partial stub in Moles.
Background
If you're not familiar with Moles I'll run through a quick explanation of how to use it. After insalling Moles open your solution in Visual Studio, go into your Test project and add a reference to whatever assembly you wish to "mole", let's call it MyProject
. You can add the reference either to an assembly directly, or to another project in the same solution.
Once you have the reference added right click on it in Solution Explorer and you should see a an option in the menu for "Add Moles Assembly".
A MyProject.moles file will be added to your test project and next time you build you will notice A MyProject.moles
reference in your project as well. The assembly has been moled and now you can start to use it.
You can download Moles from Microsoft Research here .
Using the Code
For this example the MyProject.Example
class in has two functions in it. A simple check for if a number is even, extracted into its own method IsEvenNumber
and then SomeProcess
a function that, among other things calls IsEvenNumber
.
namespace MyProject
{
public class Example
{
public virtual bool IsEvenNumber(int numberToCheck)
{
return numberToCheck % 2 == 0;
}
public string SomeProcess(int someNumber)
{
var isEven = this.IsEvenNumber(someNumber);
if (isEven)
{
return "Even";
}
return "Odd";
}
}
}
In order to test the SomeProcess
method effectively you need to isolate it. This means it can't call IsEvenNumber
in your test. You should have a separate test for IsEvenNumber
, but when testing SomeProcess
none of the code should go outside of the SomeProcess
method if you can help it.
You may have noticed that I made the IsEvenNumber
method virtual. This is necessary so that Moles can stub the method. We do this as follows:
namespace TestProject
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyProject.Moles;
[TestClass]
public class MyProjectTest
{
[TestMethod]
public void SomeProcess_StubTest()
{
var example = new SExample
{
CallBase = true,
IsEvenNumberInt32 = delegate
{
return true;
}
};
var response = example.SomeProcess(11);
Assert.AreEqual("Even", response,
"Should return Even, even though we passed in an odd number.");
}
}
}
Note that rather than instantiating our Example
class we create a new SExample
instead. This is the Moled class and allows us to stub out the methods inside of it.
CallBase = true
tells Moles that any method you call that isn't stubbed should just call the method in the base class. This way you can call example.SomeProcess()
and it will run the code, but when IsEvenNumber
gets invoked the Moled delegate takes over.
This is great for code you have influence over and can make the stubbed methods virtual. However, what happens if you don't want your method to be virtual? Or you want it to be sealed? Or you want to stub out a method in a third party assembly you have no control over?
That's where Detours come in. I've added two new methods to the Example class to test this:
public string CallsNonVirtualMethod(int someNumber)
{
var boolResponse = this.NonVirtualMethod(someNumber);
if (boolResponse)
{
return "Success";
}
return "Fail";
}
public bool NonVirtualMethod(int numberToCheck)
{
return true;
}
Like the previous example this is a simple call to a method that returns a boolean. The difference this time being that NonVirtualMethod
is, as the name suggest, not virtual. In order to test our CallsNonVirtualMethod
method you cannot stub it, but you can use a detour.
The Moled assemblies start with an M, e.g. MExample
and you can then specify a delegate for all calls to a given method. Once the detour is defined you create the instance of your class as normal and call your function. When CallsNonVirtualMethod
makes the call to NonVirtualMethod
Moles will intercept this call and run your delegate.
[TestMethod]
[HostType("Moles")]
public void SomeProcess_DetourTest()
{
MExample.AllInstances.NonVirtualMethodInt32 = delegate
{
return false;
};
var example = new Example();
var response = example.CallsNonVirtualMethod(11);
Assert.AreEqual("Fail", response,
"Should return 'Fail', even though the NonVirtualMethod is hard coded to return true.");
}
Note the [HostType("Moles")]
on the test method. This is a required attribute for Detours to work.
Points of Interest
Using Detours is more expensive than using Stubs. The Moles rely on code rewriting, which is why you have to have the
HostType
declaration.
This also means you will need to have Moles installed on your build machine as the build can't just use the referenced Moles assemblies. If possible stick
to the Stubs and enjoy greatly increased performance.
I've been a web developer since late 1995. I'm self taught and still learning.
In my spare time I'm a board game nerd and attempt entirely too many household projects that I'm not qualified for.