http://blogs.clariusconsulting.net/kzu

Daniel Cazzulino's Blog

Go Back to
kzu′s Latest post

Making WCF services amenable to testing

You know that using WebOperationContext.Current is BAD for making your service implementation testable, don’t you?

My friend Pablo Cibraro continued to evolve his ideas around decoupling your service implementation from this static dependency, and came up with the most simple yet totally unobtrusive (for production code) approach to this, which he calls WCFMock.

The idea is quite simple: you can leverage C# class aliasing functionality (which few know it even exists) to conditionally (i.e. DEBUG vs RELEASE builds) replace the WebOperationContext implementation, like so:

#if DEBUG
using WebOperationContext = System.ServiceModel.Web.MockedWebOperationContext;
#endif

What will happen here is that on DEBUG builds, the actual class invoked when your code calls WebOperationContext.Current will be different, and it will be the one that allows easy testability by providing interfaces for the context and all its properties. You can setup this mock context quite easily in your tests:

Mock mockContext = new Mock { DefaultValue = DefaultValue.Mock };

using (new MockedWebOperationContext(mockContext.Object))
{
  var formatter = catalog.GetProducts("foo");
}

// Just making sure the content type was properly set
mockContext.VerifySet(c => c.OutgoingResponse.ContentType = "application/atom+xml");

 

Of course, WCF service implementations, in my opinion, should not contain much core, and be basically a REST/webservices facade on top of the actual implementation which is something that never depends on any WCF specifics. But for those cases where you must ensure some behavior from your service implementations, this is certainly the best way to do it.

Comments

2 Comments

  1. Actually, I just figured out how to simply create the context itself. Now in my use I don’t need to mock it, I just need to verify the content coming back and the WebOperationContext.Current.OutgoingResponse.StatusCode are as expected.

    I did the following:
    var factory = ChannelFactory( theBinding, theEndpoint);
    Then I set the OperationContext.Current = new OperationContext(factory.CreateChannel() as IClientChannel);

    Everything worked just fine and I didn’t have to change anything in the service implementation, no #if (debug) or any of that.

    Now if I could only find a relevant question on StackOverflow so that this can be used by others.