Unit Testing Your DomainService Methods

Modified on Saturday, 03 April 2010 04:58 PM by Bobby Diaz — Categorized as: Uncategorized

Note: Additional information about the code on this page can be found in this blog post: Using RIA DomainServices with ASP.NET and MVC 2

Whether you subscribe to a strict TDD methodology or just write the occasional unit test, chances are that the day will come when you need to troubleshoot an issue with your WCF RIA Serivces domain service methods. If you are deriving from any of the various domain service base classes (i.e. LinqToSqlDomainService, LinqToEntitiesDomainService, DomainService), you might have already seen the dreaded "This DomainService has not been initialized." error when trying to perform even the simplest of queries.

To work around the initialization issue, we first need to create a DomainServiceContext instance and pass it into the DomainService.Initialize(DomainServiceContext) method. Doing so takes several steps, however.

1. First, create a simple ServiceProvider class that we will use later:

using System;
using System.Security.Principal;
using System.Web;

public class ServiceProvider : IServiceProvider
{
	private HttpContextBase _httpContext;

	public ServiceProvider(HttpContextBase context)
	{
		this._httpContext = context;
	}

	public object GetService(Type serviceType)
	{
		if ( serviceType == null )
		{
			throw new ArgumentNullException("serviceType");
		}

		if ( serviceType == typeof(IPrincipal) )
		{
			return this._httpContext.User;
		}
		else if ( serviceType == typeof(HttpContextBase) )
		{
			return this._httpContext;
		}

		return null;
	}
}

2. Next, create a couple of helper methods to encapsulate the creation of the DomainServiceContext. Note that the GetHttpContext() method will create a mock HttpContext instance that can be used during unit testing (not hosted in IIS).

using System;
using System.IO;
using System.Security.Principal;
using System.Web;
using System.Web.DomainServices;
using System.Web.Hosting;

public static DomainServiceContext CreateDomainServiceContext()
{
	var provider = new ServiceProvider(new HttpContextWrapper(GetHttpContext()));
	return new DomainServiceContext(provider, DomainOperationType.Query);
}

public static HttpContext GetHttpContext()
{
	var context = HttpContext.Current;

	#if DEBUG
	// create a mock HttpContext to use during unit testing...
	if ( context == null )
	{
		var writer = new StringWriter();
		var request = new SimpleWorkerRequest("/", "/", String.Empty, String.Empty, writer);

		context = new HttpContext(request)
		{
			User = new GenericPrincipal(new GenericIdentity("debug"), null)
		};
	}
	#endif

	return context;
}

3. Finally, we can initialize our domain service from within our unit test methods.

[Test]
public void Test_Service_Initialization()
{
	var context = CreateDomainServiceContext();
	var service = new NorthwindService();
	service.Initialize(context);

	var query = service.GetCustomers();
	var count = query.Count();

	Assert.Greater(count, 0);
	Console.Write("Count = {0}", count);
}

4. Extra Credit: You can combine these helper methods into a static class and create a simple extension method to tighten up the code even more!

public static class ServiceExtensions
{
	public static TService Initialize<TService>(this TService service)
		where TService : DomainService
	{
		var context = CreateDomainServiceContext();
		service.Initialize(context);
		return service;
	}

	// place other helper methods here...
}

[Test]
public void Test_Service_Initialization()
{
	var service = new NorthwindService().Initialize();
	var query = service.GetCustomers();
	var count = query.Count();

	Assert.Greater(count, 0);
	Console.Write("Count = {0}", count);
}

Hope that helps!