But can you test it?

Published on February 12, 2010

Testing code that uses HttpWebRequest directly, is a real pain.  Usually what I have seen people do is create a service interface that hides the real http client behind the interface and then create fake service implementations to actually run their tests against.  The annoying part about that solution is that Http client interfaces tend to be relatively large to fake when you consider all the properties and methods of the Http request objects and http response objects.  It is not inconceivable that the interface ends up exposing 90% of the functionality of the http client objects.

The Microsoft.Http library provides an alternative solution, assuming you don’t mind taking a dependency on it.  The HttpClient class supports the notion of a pipeline of stages with one of those stages being a transport stage that actually makes the real http request.  If we introduce a new stage prior to the transport stage we can intercept the request and return a response object with pre-canned values.  

//Arrange
var client = new HttpClient();
client.Stages.Add(new FixedTransport((key) => new HttpResponseMessage() {
   Content = HttpContent.Create("Hello World")
}));

//Act var response = client.Get("http://example.org");

//Assert Assert.AreEqual("Hello World",response.Content.ReadAsString());

 

This unit test creates a instance of the real HttpClient and adds a new processing stage called FixedTransport.  This class is available in Microsoft.Http.Test and unfortunately you cannot create your own version of this class because the method that needs to be overridden to create a custom response is marked as internal.  The Test dll can do it because it is pointed to by the InternalsVisibleTo attribute.  The only other option is to recompile the core library yourself. :-)

The FixedTransport stage is actually derived from a caching stage that can associate a URI to particular response.  In the sample above, I simply ignore the key and return the same content for all URIs.  However, this mechanism would allow you to preload the cache with a set of URI/response pairs and then you could run a test that performed multiple GET requests.

I’m not exactly sure why but from looking through the source it does appear that if you made a non-GET request the key value would be null.  That would allow you to return a specific response to a POST or PUT request based on that null key value.

I hope it is fairly obvious even after this very simple example that you should be able to easily generate pre-canned responses to standard http requests and still have access to the full capabilities of the HttpClient library without having to fake any classes.