Click here to Skip to main content
15,884,177 members
Articles / Web Development / ASP.NET

Partial Stubs and Detours with Microsoft Moles

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
29 Nov 2012CPOL3 min read 13.6K   6   5
Getting started with Stubs and Detours in Microsoft Moles

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".

Image 1

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.

Image 2

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.

C#
namespace MyProject
{
    public class Example
    {
        public virtual bool IsEvenNumber(int numberToCheck)
        {
            return numberToCheck % 2 == 0;
        }
 
        public string SomeProcess(int someNumber)
        {
            // This method does a lot of things.
            // one of those is to check if the parameter is even
            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:

C#
namespace TestProject
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using MyProject.Moles;
 
    [TestClass]
    public class MyProjectTest
    {
        [TestMethod]
        public void SomeProcess_StubTest()
        {
            // Arrange
            var example = new SExample
            {
                CallBase = true,
                IsEvenNumberInt32 = delegate
                {
                    return true;
                }
            };
 
            // Act
            var response = example.SomeProcess(11);
 
            // Assert
            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:

C#
public string CallsNonVirtualMethod(int someNumber)
{
    // This method does a lot of things.
    // one of those is to check if the parameter is even
    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.

C#
[TestMethod]
[HostType("Moles")]
public void SomeProcess_DetourTest()
{
    // Arrange
    MExample.AllInstances.NonVirtualMethodInt32 = delegate
        {
            return false;
        };
    var example = new Example();

    // Act
    var response = example.CallsNonVirtualMethod(11);

    // Assert
    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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
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.

Comments and Discussions

 
QuestionGetting compiler errors for MExample Pin
Ashish Mahamuni20-Dec-12 2:32
Ashish Mahamuni20-Dec-12 2:32 
AnswerRe: Getting compiler errors for MExample Pin
AnalogNerd20-Dec-12 3:14
AnalogNerd20-Dec-12 3:14 
GeneralRe: Getting compiler errors for MExample Pin
Ashish Mahamuni26-Dec-12 4:00
Ashish Mahamuni26-Dec-12 4:00 
GeneralRe: Getting compiler errors for MExample Pin
AnalogNerd26-Dec-12 4:51
AnalogNerd26-Dec-12 4:51 
GeneralRe: Getting compiler errors for MExample Pin
Ashish Mahamuni26-Dec-12 5:11
Ashish Mahamuni26-Dec-12 5:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.