Using Moles

Moles is a detouring framework. It uses the powerful profiling features of the CLR's just-in-time compiler to redirect method calls to custom delegates.

A common problem that demonstrates the need for a detouring framework such as Moles is when you want to run unit tests on code that depends on the DateTime.Now static property. You cannot use DateTime.Now to test specific conditions, because the value always returns the current date and time from your system clock. You also cannot directly override the DateTime.Now property to return a specific value. In this situation, you can use the Moles framework to detour the DateTime.Now property getter to your own custom delegate. This custom delegate is known as a mole.

Note

For an example of how to detour the DateTime.Now property to a custom delegate, see Moles – Detours for .NET on the Microsoft Research Web site.

When execution enters a method, such as the DateTime.Now property getter, the Moles framework checks to see whether the test class has defined a detour for that method. If a detour is defined, the framework redirects the call to the detour delegate. If a detour is not defined, the call is directed to the real implementation of the method. Alternatively, you can configure Moles to throw an exception if a detour is not defined or return a default value. For example, if a detour for the DateTime.Now property getter is defined, the method call returns the result of the detour expression. Otherwise, it uses the real implementation of the property getter to return the current date and time.

The following code example shows a test method that uses Moles to create a detour for the SPFarm.Local static property. This is a unit test for the SharePointServiceLocator class. The goal of this test is to verify that calls to SharePointServiceLocator.GetCurrent() fail if a SharePoint context is unavailable.

[TestMethod]
[HostType("Moles")]        
public void GetCurrent_CallWithoutSharePoint_ThrowsNoSharePointContextException()
{
  // Arrange
  MSPFarm.LocalGet = () => null;
  bool expectedExceptionThrown = false;

  // Act
  try
  {
    IServiceLocator target = SharePointServiceLocator.GetCurrent();               
  }
  catch(NoSharePointContextException)
  {
    expectedExceptionThrown = true;
  }

  // Assert 
  Assert.IsTrue(expectedExceptionThrown);
}

This section describes the key points of interest in this test method. First, note that a HostType attribute has been added to the method. This instructs the test runtime to execute this test within the Moles environment, which runs in a separate process. This attribute is necessary only when you use a mole, because moles rely on the profiler to detour method calls. Stubs do not involve detours, so they can run in the standard test environment.

In this test method, MSPFarm defines a mole for the SPFarm class. The naming convention for a mole is to prefix the name of the class with the letter "M". Just like stubs, moles are created in a sub-namespace, .Moles, of the namespace that contains the class we are detouring. In this case, the MSPFarm mole is defined in the Microsoft.SharePoint.Administration.Moles namespace.

In this case, the test creates a delegate for the SPFarm.Local property getter. The delegate signature, LocalGet, indicates that you are overriding the property getter for the Local property. If you could set the Local property, the mole would also have a LocalSet delegate. Because SPFarm.Local is a read-only property, the LocalSet delegate is not defined. The lambda expression, () => null, specifies that detoured calls to the SPFarm.Local property getter will return null.