Introduction
Microsoft® Moles 2010 is a Microsoft Visual Studio® 2010 add-in that helps you to isolate .NET Framework code from external dependencies, in order to test reliably whether the code performs as intended. With the Moles framework, you can replace any method that the code-under-test calls with a test implementation that uses a delegate.
Background
Visual Studio Test Explorer already supports the developers who can incorporate unit testing in their software development practices. Unit testing helps you ensure the correctness of your program by verifying that the application code does what you expect it to do. Test Explorer provides a flexible and efficient way to run your unit tests and view their results in Visual Studio.
So why moles framework when Unit testing is so good?
I am sure all developers must have written the unit test cases for there code. Accepting something new like Moles Framework will not be easy for them. So let’s analyze the problems with the current unit testing concept.
When we write a unit test case for a class, we are actually looking forward to test the functionality of that particular class, not for all the code on which our concerned class is dependent on. Say for example, you write class X which is dependent on class Y, that is class Y is called from class X. So when you write the test case for your class X, it will internally call the class Y.
We can summarize the limitation of unit testing as:-
- Making testing an integration testing.
- For running the test case, you now have to understand the complexity of class X, but also for class Y.
- If any change in class Y is made, the unit test case for the class X is also required to change.
- If our class Y is making a call to a database or to a file, of which we do not have the authority our test case might fail even if the purpose of testing class X was served.
So for overcoming these problems, Microsoft has come up with the moles framework.
Pre-requisite for Moles Framework
Before we start learning let's ensure that you have all the ingredients to create an first mole test application.
- Windows® 7, Windows Vista®, or Windows Server®2008 R2 or later operating system
- Visual Studio 2010 Professional
Microsoft Moles also work with Visual Studio 2008 Professional; this tutorial assumes that your edition supports the Visual Studio Unit Testing framework.
So once you have all your pre-requisites it is time to start.
The Moles Framework
The moles framework allows us to create substitute classes for code dependencies under different circumstances, to test individual components in isolation and to make testing more robust and scalable.
It allows replacing any .NET method with a delegate. In the context of unit testing, you can use Moles to isolate from environment dependencies such as time, file system, database, and so on, even when those dependencies are hard-coded through static method or sealed types.
- A common approach is to use dummy implementations, called ‘test stubs’ -for components that are not currently under test. Ex: interfaces
- For the code that does not allows the use of test stubs, then mole framework allows ‘detouring’ of hard-coded dependencies. Ex: Static Methods
Stub type
In the Moles framework, it is specifically a type generated for interfaces and non-sealed classes, which allows you to redefine the behavior of methods by attaching delegates.
Mole type
When refactoring is not possible, we can use runtime instrumentation to detour the method. To do this, we use the Moles framework to create mole types, which take advantage of runtime instrumentation. They are useful when dealing with APIs with static methods, sealed types, or non virtual methods.
To install Moles
- Download Moles to start installation
- As with all Windows software, accept the prompt to run the software.
- Click Next on the Setup Wizard Welcome page, and accept the license agreement to proceed.
- Choose Setup Type—Typical, Custom, or Complete—and then click Install.
Using the code
For using the mole framework, we will first create the sample application and the test project.
Task 1: Create the Application Project for stub type
To create the sample application project
Create the Class Library Project
- In Visual Studio, click File > New > Project.
- In the left pane of the Add New Project dialog box, click Visual C#.
- In the right pane of the Add New Project dialog box, click Class Library.
- Rename the project StubsTutorial and click OK.
Create a Test for the Class Library
- Open the newly created StubsTutorial solution, if it is not already open.
- In Visual Studio, click File > New > Project.
- In the left pane of the New Project dialog box, expand Visual C#, and click Test. In the center pane, click Test Project. In the Solution drop-down list, click Add to solution.
- Rename the project StubsTutorialTest, and click OK.
- In the Solution Explorer, right-click the References node under StubsTutorialTest, and click Add Reference from the context menu click the Projects tab, click StubsTutorial, and click OK.
- In Visual Studio, open the test project StubsTutorialTest, open the References node, right-click the StubsTutorial reference node and select Add Moles Assembly.
- Some .moles file is now added to the project, which is a simple XML file that specifies the assembly that should be moled and stubbed. Open the file to see.
Now you are done with the basic architecture for using the moles framework.
For learning how actually the framework works, Lets add a class to the above created class library:
- In Visual Studio, right-click the StubsTutorial node, click Add, and then click Class
- In the left pane of the Add New Item dialog, click Visual C# Items. In the center pane, click Class. Then rename the class to Virtual.cs and click Add.
- Open the Virtual.cs class and replace the content of the class with the following snippet:
public class Virtual
{
public virtual bool IsEvenNumber(int numberToCheck)
{
returnnumberToCheck % 2 == 0;
}
public string SomeProcessVitual(int someNumber)
{
var isEven = this.IsEvenNumber(someNumber);
if (isEven)
{
return "Even";
}
return "Odd";
}
}
In the above class you have two methods. SomeProcessVitual
is calling IsEvenNumber
method. So if you write the traditional unit test case for SomeProcessVitual
method, the test case will internally call IsEvenNumber
method, hence making it as integrated testing. To overcome this, we will here create the dummy implementation for IsEvenNumber
method, so the dependency on the method can be removed.
So what will happen is, when your method SomeProcessVitual
will internally call IsEvenNumber
method, it will not go to the actual implementation, but will execute our dummy implementation.
To achieve the above, add a unit test case to the above created test project:
- In the StubsTutorialTest project, Add a test class rename it to TestReaderTest.cs and open it for editing.
- Replace the content of the file with the following snippet, which adds the unit test with the Arrange, Act, and Assert steps:
[TestClass]
public classVirtualTest
{
[TestMethod]
public voidVirtual_SomeProcess_StubTest()
{
varvirtualM = new SVirtual();
virtualM.IsEvenNumberInt32 = delegate(int n)
{
returntrue;
};
varresponse = virtualM.SomeProcessVitual(11);
Assert.AreEqual("Even", response,
"Should return Even, even though we passed in an odd number.");
}
}
Now, try debugging you test class. You will here note that when you call SomeProcessVitual
, it will not call the actual implementation of IsEvenNumberInt32
method, rather it will call the dummy implementation, which you have created in the above test class.
Now, what if you cannot redefine your method definition, for example say how you will create the dummy implementation for the static method. For this Microsoft has provided us with mole type, which allows us to use runtime instrumentation to detour the method
For using the Mole type, we will use the above created project.
- In Visual Studio, starting with the project from the previous task, add a class to the project : StaticMethod.
- Add the following code to it
publicclass StaticMethod
{
public staticint MyMethod(intn)
{
returnn;
}
}
- Add a class in test project: StaticMethodTest.
- Add the below code to the class:
[TestClass()]
public class StaticMethodTest
{
[TestMethod()]
[HostType("Moles")]
public voidStatic_MyStaticMethodTest()
{
var content1 = 21;
MStaticMethod.MyMethodInt32 = delegate(int n1)
{
return content1;
};
var test1 = StaticMethod.MyMethod(11);
Assert.AreEqual(content1, test1);
}
}
Because mole types require runtime instrumentation, the Moles runtime runs under [HostType("Moles")]
. If you remove [HostType("Moles")]
from the test, the code does not get instrumented and Moles will throw an exception “Moles requires tests to be in an instrumented process.”
The Moles framework provides strongly typed wrappers that allow you to redirect any .NET method to a user defined delegate. These wrappers are called mole types, after the framework that generates them. A method that has been wrapped like this is referred to as moled.
Generally Refactoring is the preferred method of isolation, because it does not require runtime instrumentation. However, refactoring is often not a choice—in which case, runtime instrumentation might be the only solution.
Points of Interest
Mole Type and Stub Type Naming Conventions
Namespace
- Moles suffix is added to the namespace. Example:
System.Moles
namespace contains the Mole types of System
namespace.
Global.Moles
contains the mole type of the empty namespace.
Type Names
- M prefix is added to the type name to build the mole type name. Example: MExample is the mole type of the
Example
type.
- S prefix is added to the type name to build the stub type name. Example: SIExample is the stub type of the
IExample
type.
Type Arguments and Nested Type Structures
- Generic type arguments are copied.
- Nested type structure is copied for mole types.
Feature
|
Stub types
|
Mole types
|
Detour mechanism
|
Virtual method overriding
|
Runtime instrumentation
|
Static methods, sealed types
|
No
|
Yes
|
Internal types
|
Yes
[InternalsVisibleTo(…)] attribute
|
Yes
|
Private methods
|
No
|
Yes
|
Static Constructors and Finalizers
|
No
|
Yes
|
Performance
|
Fast
|
Slower
|
Abstract methods
|
Yes
|
No
|