In my previous post, I talked about how to design a class that uses a WCF client proxy in such a way to make it testable in unit tests, without having to spin up a real service to answer the requests. The technique I illustrated uses a particular Inversion of Control (IoC) principle called Dependency Injection (DI), in which objects that a given class depends on get pushed into it from the outside rather than being created internally.
In this particular case, the external dependency is represented by a WCF client proxy targeting a particular service. This approach enables me to swap the real proxy objects used in production with test doubles while running unit tests, making it possible to assert the class’s behavior in a completely isolated and controlled environment.
Last time we left off with a MailClient
class that takes an instance of ChannelFactory
in the constructor and uses it internally every time it needs to download Email messages by following three steps:
MailService
serviceGetMessages
operation on the serviceHowever, as I pointed out before, being the ChannelFactory a concrete class, creating a test double for it isn’t very convenient. A much better approach would be having the MailClient class** interact with an interface instead. This way it would be easy to create a **fake factory object in unit tests and have the class use that instead of the real one.
After a quick look in the online MSDN Documentation I found that the ChannelFactory class indeed implements the IChannelFactory interface. “Sweet, I can use that!” I thought. But there’s a catch:
The IChannelFactory<TChannel>.CreateChannel
factory method requires the caller
to pass along an EndpointAddress
object, which contains information about where
and how to reach the service, like the URI and the Binding.
This isn’t really what I wanted, since it forced the MailClient
class to have knowledge of where the remote service is located or at the very least how to obtain that piece of information. This doesn’t really conform to the Dependency Injection principle, since these details naturally belong to the dependent object, and should therefore be handled outside the scope of the class.
The solution I came up with is to create an adapter interface to hide these details from my class. The implementation of this interface would then wrap a properly configured instance of ChannelFactory and delegate all the calls it receives to it.
Here is the definition of the adapter interface:
using System.ServiceModel;
public interface IClientChannelFactory<TChannel>
where TChannel : IClientChannel
{
void Open();
void Close();
void Abort();
TChannel CreateChannel();
}
And here is the default implementation:
using System;
using System.ServiceModel;
public class ClientChannelFactory<TChannel> : IClientChannelFactory<TChannel>
where TChannel : IClientChannel
{
private ChannelFactory<TChannel> factory;
public ClientChannelFactory(string endpointConfigurationName)
{
this.factory = new ChannelFactory<TChannel>(endpointConfigurationName);
}
public void Open()
{
this.factory.Open();
}
public void Close()
{
this.factory.Close();
}
public void Abort()
{
this.factory.Abort();
}
public TChannel CreateChannel()
{
return this.factory.CreateChannel();
}
}
As you can see by using generics we are able to create an implementation that works for different types of proxies.
Notice also that the class requires the callers to specify the name of the configuration element used to describe the service endpoint in the constructor. This way the MailClient class is completely isolated from having to know about WCF configuration details, and can instead concentrate on its core responsibility, that is to invoke operations on the service and work with the results.
Here is the final MailClient
implementation:
public class MailClient
{
private IClientChannelFactory<IMailServiceClientChannel> proxyFactory;
public MailClient(IClientChannelFactory<IMailServiceClientChannel> proxyFactory)
{
this.proxyFactory = proxyFactory;
}
public EmailMessage[] DownloadMessages(string smtpAddress)
{
// Validate the specified Email address
IMailServiceClientChannel proxy;
try
{
proxy = proxyFactory.CreateChannel();
Mailbox request = new Mailbox(smtpAddress);
EmailMessage[] response = proxy.GetMessages(request)
// Do some processing on the results
proxy.Close();
return response;
}
catch(Exception e)
{
proxy.Abort();
throw new MailClientException("Failed to download Email messages", e);
}
}
}
The only modification is in the type of the argument declared in the constructor, which is now an interface.
We are now able to test our class in isolation by creating fake objects that implement the IClientChannelFactory
and IMailServiceClientChannel
interfaces respectively, and inject them into our object under test.
In this particular example I am using Rhino Mocks as an isolation framework to create and manage test doubles, but I could as well used just about any other isolation framework out there, such as Typemock Isolator, with the same result.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
[TestClass]
public class MailClientTest
{
[TestMethod]
public void DownloadMessages_WithValidEmailAddress_ReturnsOneMessage()
{
// Fakes out the WCF proxy
var stubProxy = MockRepository.CreateStub<IMailServiceClientChannel>();
// Stubs the service operation invoked by the class under test
stubProxy
.Stub(m => m.GetMessages(Arg.Is.Anything))
.Returns(new EmailMessage[0]);
// Fakes out the WCF proxy factory
var stubProxyFactory = MockRepository.CreateStub<IClientChannelFactory<IMailServiceClientChannel>>();
// Stubs the factory method to return the mocked proxy
stubProxyFactory
.Stub(s => s.CreateChannel())
.Return(stubProxy);
var testObject = new MailClient(stubProxyFactory);
EmailMessage[] results = testObject.DownloadMessages("[email protected]");
Assert.AreEqual(0, results.Length, "The method was not supposed to return any results");
}
}
This concludes this short series of posts on how to apply Dependency Injection to classes that consume WCF services in order to easily test them in isolation with unit tests. I hope this helps.
/Enrico
I have to admit that in the beginning I didn’t think Inversion of Control (IoC) Containers were that big of a deal. The idea of relying on an external agent to manage all the associations between objects in an application, sounded like it would bring more problems than advantages. Overkill. But I was wrong.
Since I began using IoC containers in my projects, I found that it naturally leads to loosely-coupled structures in the software. This is due to two key design principles that an IoC container will enforce you to follow:
This decoupling contributes in making the software easily testable and ready for evolution.
In my last project I was designing classes that would need to interact with different Web Services through WCF client proxies. I needed to test those classes in isolation in my unit tests, without having to have my WCF service host process running in the background, so I figured I would let an instance of a WCF proxy be pushed from outside the classes through an interface, as a dependency, instead of creating it internally, like I would normally do.
This idea fits well with the way tools like svcutil and Visual Studio 2008 work when generating WCF client proxies, since they create a class as well as interfaces exposing the operations that can be invoked through the proxy.
So here is my first implementation:
public class MailClient
{
private IMailServiceClientChannel proxy;
public MailClient(IMailServiceClientChannel proxy)
{
this.proxy = proxy;
}
public EmailMessage[] DownloadMessages(string smtpAddress)
{
// Validate the specified Email address
Mailbox request = new Mailbox(smtpAddress);
EmailMessage[] response = proxy.GetMessages(request)
// Do some processing on the results
return response;
}
}
Here I am using the IMailServiceClientChannel
interface that is automatically generated by Visual Studio when adding a service proxy with the Add Service Reference dialog. This interface contains the signatures of all the operations that are part of the service contract, as well as WCF-specific infrastructure methods to manage the proxy, like Open and Close.
This didn’t feel quite right. I was not treating the WCF proxy like I should since I was not closing it properly after being done with it, and not having any sort of error handling code.
However, at a second thought, I realized this wasn’t really the responsibility of my class. Since I wasn’t creating the proxy instance myself but was instead receiving from the outside, I couldn’t really dispose it inside my method, because it could still be needed by the caller. So here is an alternative implementation:
public class MailClient
{
private ChannelFactory<IMailServiceClientChannel> proxyFactory;
public MailClient(ChannelFactory<IMailServiceClientChannel> proxyFactory)
{
this.proxyFactory = proxyFactory;
}
public EmailMessage[] DownloadMessages(string smtpAddress)
{
// Validate the specified Email address
IMailServiceClientChannel proxy;
try
{
proxy = proxyFactory.CreateChannel();
Mailbox request = new Mailbox(smtpAddress);
EmailMessage[] response = proxy.GetMessages(request)
// Do some processing on the results
proxy.Close();
return response;
}
catch(Exception e)
{
proxy.Abort();
throw new MailClientException("Failed to download Email messages", e);
}
}
}
This time instead of using a proxy instance, the class receives a ChannelFactory instance as an external dependency through the constructor.
Channel factories in WCF are the facilities used to create the pipelines through which incoming and outgoing messages pass before being dispatched to the receiver or sent out over the wire.
This approach allows me to create a new proxy instances by invoking the ChannelFactory.CreateChannel method ad-hoc inside the class and to properly dispose them as soon as I no longer need them.
According to sources inside the WCF team at Microsoft, it is a best practice to create proxies by reusing the same ChannelFactory object, instead of creating a new proxy objects from the class generated by Visual Studio, since the cost of initializing the factory is paid only once.
This turns out to be a much better approach to assign WCF proxies to classes through Dependency Injection (DI) because now I can create instances of the MailClient class using my IoC of choice, which happens to be Microsoft Unity, with a couple of lines of code:
// Registers the ChannelFactory class with Unity
// and specifies the name of the endpoint to use
// as stated in the configuration file
var container = new UnityContainer();
container
.RegisterType<ChannelFactory<IMailServiceClientChannel>>()
.Configure<InjectedMembers>()
.ConfigureInjectionFor<ChannelFactory<IMailServiceClientChannel>>(
new InjectionConstructor("localMailServiceEndpoint"));
var client = container.Resolve();
// The object has now its dependencies already setup
// and is ready to be used
client.DownloadMessages("[email protected]");
Here I’m registering the ChannelFactory
class with the IoC container, telling it to pass the string localMailServiceEndpoint
in the constructor whenever a new instance is created.
The ChannelFactory will use that value to look up in the configuration file the URL where the service is located and the protocol it should use to communicate with it, like in this sample WCF configuration:
<configuration>
<system.serviceModel>
<client>
<endpoint
name="localMailServiceEndpoint"
address="http://localhost/mailservice"
binding="wsHttpBinding"
contract="IMailServiceClient"
/>
</client>
</system.serviceModel>
</configuration>
With this information in place, I’m now able to ask the container to construct an instance of the MailClient
class, and it will automatically resolve the dependency on the WCF ChannelFactory for me.
Well, the ChannelFactory is a concrete class and, although certanly possible, can’t easily be faked out (through mocks or stubs) by using one of the common mocking isolation frameworks available out there, since it requires the presence of a configuration file with the proper WCF-specific settings in order to work correctly. This makes the MailClient class still hard to test in isolation.
In my next post I will explain a way to modify this sample to be able to write unit test for classes that use WCF proxies.
/Enrico
An interesting trend has emerged in the .NET community during the past couple of years, which involves developers sharing their favorite color theme for the Visual Studio code editor with their peers.
It seems the origin of this trend is somehow related to the introduction of a new feature in Visual Studio 2005 that makes it really easy to export/import all or a subset of the customizations made to the IDE’s into a single XML file. These settings files (.vssettings) include every configurable aspect of Visual Studio, from font colors and window sizes to keyboard shortcuts. Useful for backups as well as for keeping Visual Studio the way you like it every time you switch to work on a different computer.
What developers are most excited about, however, is exchanging the color combinations they use for the text editor included in the IDE, referred to as “themes”.
It’s interesting to notice how a fair amount of developers seem to prefer light text on a dark background, as opposed to the traditional “black on white” paper metaphor introduced by the word processors. These themes mimic the colors used by the classic programmer text editors of the past, like VIM and EMACS running on DOS or UNIX, which used to sport dark gray or bright blue backgrounds.
Colors are entirely a matter of personal taste, and in this regard I prefer the clean contrast of white text on black background. Some people even argue that dark backgrounds are easier on the eyes than white ones, due to the reduced amount of bright light emitted by the computer screens. However I don’t know of any official study conducted to scientifically prove this statement.
Being a developer myself, I also tweaked my own color theme for the text editor I use to write code on a daily basis, which in my case is Microsoft Visual Studio 2008. I took inspiration from other themes I’ve seen around on the Internet and adjusted them to my taste. In the end, I settled for the following:
It’s a high contrast scheme, but I feel comfortable with it since the colors are not as sharp as other similar ones like John Lam’s Vibrant Ink.
Here is how a C# file looks like with it:
And here is how an XML file looks like:
You can download my Visual Studio color theme here. I have used it for quite a while now and I am pretty satisfied with it. However, I fell I’ll probably tweak it some more in the future. After all, there is always room for improvements.
I’ve modified my dark theme to work in Visual Studio 2010. Most of the settings worked straight way, so I only needed to make some minor changes like adding support for T-SQL keywords. By the way, the custom colours for user types and interfaces now finally work in Visual Basic too. You can download the Visual Studio 2010 theme from the link below.