Unit testing DelegatingHandler

The DelegatingHandler in the MVC 4 beta Web API is not particularly easy to test due to the inheritance dependency on DelegatingHandler and the use of overridden protected methods. All is not lost though, by using the following pattern you can achieve testability of the logic with subtle changes to your existing DelegatingHandler and without breaking the Russian Doll pattern.

Create a delegate as follows:

public delegate Task<HttpResponseMessage> BaseSendAsyncDelegate(HttpRequestMessage request, CancellationToken cancellationToken);

Changing your DelegatingHandler to the following (note you’ll also need to add InternalsVisibleTo attribute for your unit test to see the handler):

public class MyTestableDelegatingHandler : DelegatingHandler
{
    internal Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken, BaseSendAsyncDelegate baseSendAsync)

{

        // Your before logic
        // …
       
return baseSendAsync(request, cancellationToken).ContinueWith(
            task =>
                {
                    HttpResponseMessage response = task.Result;
                       
                    // Your after logic
                   
return response;
            });
    }       
      
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        // Don’t put anything else in this method
       
return this.SendAsync(request, cancellationToken, (r, c) => base.SendAsync(r, c));
    }
}

Tests

Now the logic can be called without the overhead of the DelegatingHandler as follows:

[TestMethod]
public void MyTest()
{
    MyTestableDelegatingHandler logic = new MyTestableDelegatingHandler();
    HttpRequestMessage requestMessage = new HttpRequestMessage();

    Task<HttpResponseMessage> result = logic.SendAsync(
        requestMessage,
        new CancellationToken(false),
        (rm, ct) =>
            {

                // Do some Asserts in here for any “Before” logic

                // This simulates what the inner handler (or ultimately the controller) would return
                var task = new Task<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.OK));
                task.Start();
                return task;
            });

    HttpResponseMessage resultMessage = result.Result;
    var status = resultMessage.StatusCode;
   
    // Do Asserts here for any “After” logic
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s