Implementing WCF Services Without Referencing WCF

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.

Comments (4)

  1. ploeh blog says:

    In my previous post , I explained how to implement a WCF service without referencing WCF. In simple cases,

  2. ploeh blog says:

    One of my readers recently asked me about unit testing WCF services when they have callbacks. Given that

  3. Paul Gamblen says:

    Hi Mark.

    We use Juval Lowrys InProcFactory for unit testing our services. It doesnt work for all WCF configurations but in the most part suffices for what we want to do. We have extended ClientBase to either use a hosted version of the service or an in process version of the service based on configuration.

    Thought you might be interested.


  4. ploeh says:

    Hi Paul

    Thank you for your tip. There are, as far as I know, a couple of third party InProc transports for WCF. I normally use the named pipes transport for unit testing, although a faster transport would be nicer.

    Personally, I don’t find that the added overhead of having to reference and manage yet another library to gain a bit of speed is worth the effort, but YMMV. Not that test speed is unimportant, but I find the named pipes transport sufficiently fast to my purposes.

    This whole discussion is orthogonal to the subject of this post, which is about how you completely remove WCF from your service implementation. There’s a lot of good reasons for doing that, and increased test speed is only a side effect.

    That’s not to dismiss your idea at all. I think it’s a valid contribution that may be beneficient to a lot of people, so I thank you for sharing 🙂