In today’s service-oriented architectures, unit testing is more challenging than ever. How do you isolate and test a service that depends on five other services?
One way is to mock those dependent services. The example we’ll work through has three components:
- WcfApp - A WCF application that can get data about customer preferences. Specifically, we want to know each customer’s favorite item on a menu.
- CouponGenerator - Generates coupons based on customers’ favorites. This assembly calls WcfApp to learn what each customer’s favorite is.
- CouponGeneratorTests - The unit-test assembly for CouponGenerator.

Our problem: We want to be able to test the CouponGenerator assembly without relying on the WcfApp.
The solution will be to use Moq to mock the WCF application, and the Unity dependency-injection framework to inject the mock.
Let’s work our way from the inside out, starting with the WCF application.
The WCF Service Application
The ICustomerPreferences service contract and its implementation couldn’t be simpler.
using System.ServiceModel;
namespace WcfApp
{
[ServiceContract]
public interface ICustomerPreferences
{
/// <summary>
/// Gets the customer's favorite item on the menu.
/// </summary>
/// <param name="customerId">The unique ID of the customer.</param>
/// <returns>The customer's favorite.</returns>
[OperationContract]
string GetFavoriteMenuItem(int customerId);
}
}
namespace WcfApp
{
public class CustomerPreferences : ICustomerPreferences
{
/// <summary>
/// Gets the customer's favorite item on the menu.
/// </summary>
/// <param name="customerId">The unique ID of the customer.</param>
/// <returns>The customer's favorite.</returns>
public string GetFavoriteMenuItem(int customerId)
{
return "Jumbo Burger";
}
}
}
The Coupon Generator
This is the assembly that depends on the WCF application, and that dependency is what we want to break.
The coupon generator contains a service reference generated by Visual Studio. (In production I prefer to craft my own, using a library of goodies I’ve developed for the purpose, but Visual Studio’s service references are familiar to everyone so let’s go that route for now.)
The main class of interest, Coupon, calls the WCF service in the process of creating a simple, text-based coupon. However, it does not use the generated Service Reference directly. Instead, it uses Unity to point to either the real WCF service or the mock we’ll discuss in a moment.
Normally, the code would go like this:
var proxy = new CustomerPreferencesClient();
var fave = proxy.GetFavoriteMenuItem(CustomerId);
The Unity dependency-injection framework allows us to specify in a configuration file what class we want to instantiate for an ICustomerPreferences contract. It takes just one additional line of code.
var unity = new UnityContainer().LoadConfiguration();
var proxy = unity.Resolve<ICustomerPreferences>();
var fave = proxy.GetFavoriteMenuItem(CustomerId);
In our case, we want to inject a CustomerPreferencesMock, which is in our unit testing assembly. More on that in a moment; first, here is the complete listing for Coupon.cs.
using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using CouponGenerator.ServiceReference1;
namespace CouponGenerator
{
public class Coupon
{
public int CustomerId { get; set; }
public Coupon(int customerId)
{
CustomerId = customerId;
}
public string[] AsText()
{
// Without Unity's dependency injection:
//var proxy = new CustomerPreferencesClient();
// With dependency injection:
var unity = new UnityContainer().LoadConfiguration();
var proxy = unity.Resolve<ICustomerPreferences>();
try
{
var fave = proxy.GetFavoriteMenuItem(CustomerId);
var strings = new List<string>();
strings.Add("------------------------------------------------------------");
strings.Add("COUPON");
strings.Add(String.Format("You get 10% off your next {0} order!", fave));
strings.Add("------------------------------------------------------------");
return strings.ToArray();
}
finally
{
if (proxy is IDisposable)
(proxy as IDisposable).Dispose();
}
}
}
}
The Unit Testing Assembly
Our first unit test looks like this. We instantiate a Coupon and make sure it has the right text.
[TestMethod]
public void AsText_GoodCustomerId_DefaultMock()
{
int customerId = 100;
var coupon = new Coupon(customerId);
var expected = new string[]
{
"------------------------------------------------------------",
"COUPON",
"You get 10% off your next Fish and Chips order!",
"------------------------------------------------------------",
};
var actual = coupon.AsText();
Assert.IsTrue(expected.SequenceEqual(actual));
}
Here’s the magic. Because we coded the Coupon class to use Unity, the unit test’s app.config can inject a mock class:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="CouponGenerator"/>
<assembly name="CouponGeneratorTests"/>
<container>
<register type="CouponGenerator.ServiceReference1.ICustomerPreferences"
mapTo="CouponGeneratorTests.CustomerPreferencesMock" />
</container>
</unity>
</configuration>
What’s in the mock? Notice the following features in the next listing.
- It inherits from ICustomerPreferences. This must be the case if we are going to use Unity to inject it as our stand-in for the real implementation of ICustomerPreferences.
- It has a static Mock property which gets initialized on first use.
- Initialize() sets up a sort of fake database by telling the mock to return “Fish and Chips” for one customer and “Pepperoni Pizza” for another.
- The implementation of ICustomerService delegates to the corresponding method in the mock.
using Moq;
using CouponGenerator.ServiceReference1;
namespace CouponGeneratorTests
{
public class CustomerPreferencesMock : ICustomerPreferences
{
#region Properties
static Mock<ICustomerPreferences> _mock = null;
/// <summary>
/// Static property to access the Mock of ICustomerPreferences
/// </summary>
static public Mock<ICustomerPreferences> Mock
{
get
{
if (_mock == null)
Initialize();
return _mock;
}
}
#endregion
#region Initialize
/// <summary>
/// Reset the Mock to the default fake values.
/// </summary>
static public void Initialize()
{
_mock = new Mock<ICustomerPreferences>();
_mock
.Setup(custPrefs => custPrefs.GetFavoriteMenuItem(It.Is<int>(id => id == 100)))
.Returns("Fish and Chips");
_mock
.Setup(custPrefs => custPrefs.GetFavoriteMenuItem(It.Is<int>(id => id == 101)))
.Returns("Pepperoni Pizza");
}
#endregion
#region ICustomerPreferences Implementation
public string GetFavoriteMenuItem(int customerId)
{
return Mock.Object.GetFavoriteMenuItem(customerId);
}
#endregion
}
}
Because Mock is exposed as a static property, our unit tests can modify the mock. Here we have changed customer 100’s preference from Fish and Chips to Steak Sandwich.
[TestMethod]
public void AsText_GoodCustomerId_ModifiedMock()
{
int customerId = 100;
string fave = "Steak Sandwich";
CustomerPreferencesMock.Mock
.Setup(custPrefs => custPrefs.GetFavoriteMenuItem(It.Is<int>(id => id==customerId)))
.Returns(fave);
var coupon = new Coupon(customerId);
var expected = new string[]
{
"------------------------------------------------------------",
"COUPON",
String.Format("You get 10% off your next {0} order!",fave),
"------------------------------------------------------------",
};
var actual = coupon.AsText();
Assert.IsTrue(expected.SequenceEqual(actual));
}
Running the Tests
When you run the tests, you will see that the WCF service does not even start. You could actually delete it from your drive and the tests would work.
Of course, you’d still want integration tests to make sure the WCF aspects of your system were working, but our focus here is on the unit tests.
Benefits
This decoupling has several benefits.
- You’ll be more productive because your unit tests will be much faster.
- You’ll also be more likely to write lots of unit tests if you don’t have to pay a penalty every time they run.
- Your test environment will be much easier to set up, since you’ll have fewer environmental dependencies. For example, you won’t care if your WCF service uses a database because you’re not actually running the service.
Configuring for Production
In production, all we have to do is use a config file that names the real client instead of the mock.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="CouponGenerator"/>
<assembly name="CouponGeneratorTests"/>
<container>
<register type="CouponGenerator.ServiceReference1.ICustomerPreferences"
mapTo="CouponGenerator.ServiceReference1.CustomerPreferencesClientUnityFriendly" />
</container>
</unity>
</configuration>
However, there’s one small annoyance. You may have noticed the mapTo name: CustomerPreferencesClientUnityFriendly. Here's what's going on with that. Unity likes to use the constructor with the most parameters. In the case of the CustomerPreferencesClient that Visual Studio generated, there are three that fit this description, each with two parameters. Unity will be confused because it doesn't know which of the three to use. There are various ways to help Unity out of this confusion. The one I’ve chosen is to create a separate, Unity-friendly client that inherits from the one Visual Studio generated. The Unity-friendly client has only a default constructor. Problem solved.
namespace CouponGenerator.ServiceReference1
{
/// <summary>
/// Unity-friendly extension of the CustomerPreferencesClient.
/// It's Unity-friendly because there's no ambiguity among constructors.
/// </summary>
public class CustomerPreferencesClientUnityFriendly : CustomerPreferencesClient
{
public CustomerPreferencesClientUnityFriendly()
{ }
}
}
Summary
We have seen how to create a mocked version of a WCF service, and how to inject it into your unit tests with Unity. The mocked version can contain fake data, but you can also override the mock in individual tests.
The benefits are faster tests and fewer environmental dependencies.