More than a year ago, I wrote my first post on unit testing WCF services. One of my points back then was that you have to be careful that the service implementation doesn't use any of the services provided by the WCF runtime environment (if you want to keep the service testable). As soon as you invoke something like OperationContext.Current, your code is not going to work in a unit testing scenario, but only when hosted by WCF.
This point is as true today as it was one and a half year ago.
So how do you ensure that you don't accidentally invoke WCF runtime services in the service code?
By being very, very careful..?
Unless you are very disciplined and work alone on the service, that's probably not a very good solution. While you may be skillful enough to pull it off, Joe Junior Programmer is going to come along during your one week of vacation and mess it all up.
Fortunately, a more robust solution exists: You can actually implement a WCF service without referencing WCF at all. How about that?
Obviously, when declaring the service contract, you will need to reference System.ServiceModel to put the right attributes on the contract:
public interface IStuffService
void DoStuff(string stuff);
The contract library contains only the contract, but no implementation. The concrete implementation can be placed in a separate library that doesn't reference System.ServiceModel. As long as you have a reference to the contract library, you can still implement the service:
public class StuffService : IStuffService
#region IStuffService Members
public void DoStuff(string stuff)
// Implementation goes here... }
Since the entire WCF part of the contract is specified using attributes, you don't need a reference to System.ServiceModel in the implementation library even though the contract library requires this reference.
Now you can implement the service without fear of accidentally adding WCF dependencies, since you don't have a reference to WCF at all.
To prevent other developers from accidentally adding a reference to System.ServiceModel while you are away, you can actively enforce that convention, as exemplified in Glenn's post.
In very simple cases, this is all you need to do, but I'll admit that this example is a bit naive; as soon as you need to apply behaviors or other WCF-specific modifications to the service, it becomes more complex. In many cases, this is done by applying attributes to the service implementation (such as ServiceBehaviorAttribute), but this is not possible when you don't have a reference to System.ServiceModel.
In a future post, I'll explain how to get around some of these issues. Update: This post is now available here.