
.NET 3.5+Generate Return Values Using Lambdas in Moq
Mock objects and stubs created using the Moq framework are generally used to inject dependencies with expectations that define fixed results. For more complex scenarios, lambda expressions can be used to generate results based on provided arguments.
Moq Expectations
In previous articles I've described how mocks and stubs created using the Moq isolation framework can be configured with expectations. These expectations define the result of using a member of the mocked interface or class and can include returning a value or throwing a predefined exception. The examples have included expectations that return a fixed value. However, in some cases your unit tests will require more flexibility from their mocked dependencies. For example, you may wish that the value returned from a parameterless method or property varies over time, or you may want to use the values passed to a member's parameters in a calculation that generates a return value. You can achieve this by using a
lambda expression in the Returns section of an expectation.
Creating a Test Interface and Mock Object
Let's start with a simple example using an expectation for a method that does not accept arguments. Firstly, we need an interface to mock. We will use the ITestObject interface shown below. This includes two methods; one has no parameters and one accepts two integer arguments. Both return 64-bit integer results.
public interface ITestObject
{
long GetResult();
long CalculateResult(int x, int y);
}
We can now create a mock ITestObject using the following code:
Mock<ITestObject> mockTestObject = new Mock<ITestObject>();
Creating an Expectation that Returns the Result of a Lambda Expression
With the mock object in place we can try setting some expectations and checking that the results are as we expect. For the purposes of this article I will not show unit tests; we will output the results of calling the mocked interface's methods to the console. Although this is not a typical use, it demonstrates the syntax without requiring an additional test framework such as NUnit.
We'll begin with a typical expectation for the GetResult method. The code below initialises the expectation, returning the current date and time as a number of ticks.
mockTestObject.Setup(m => m.GetResult()).Returns(DateTime.Now.Ticks);
The above code is ideal if you wish to fix the number of ticks returned. The DateTime.Now.Ticks property is evaluated when creating the expectation so the mock object will always return the same value. We can see this by executing the method twice and outputting the results:
ITestObject test = mockTestObject.Object;
Console.WriteLine(test.GetResult()); // 634601518560535048
Console.WriteLine(test.GetResult()); // 634601518560535048
If you want to delay the evaluation of the returned value, you can provide Moq with a lambda expression to run when the expectation is met. The lambda is executed each time the expectation is triggered, giving a different result each time. This is shown in the code below. Note that the value passed to the Returns method has been changed to be a lambda expression and the outputted values now differ.
mockTestObject.Setup(m => m.GetResult()).Returns(() => DateTime.Now.Ticks);
ITestObject test = mockTestObject.Object;
Console.WriteLine(test.GetResult()); // 634601519452316055
Console.WriteLine(test.GetResult()); // 634601519452326056
NB: Using a lambda expression in this manner can be used to queue return values, allowing a series of fixed values to be returned from a single expectation.
22 December 2011