Mark Gilbert's Blog

Science and technology, served light and fluffy.

Queue them up! Unit testing HttpClient

Early in my current project, I was looking for a way to test some logic that relied on HttpClient.PostAsync.  I was writing a routine that would process items coming off a queue that was exposed via a series of REST services.  Subscribing to the queue, pulling messages down, and cleaning the subscription up once the queue was empty all required calls to the services, and in most cases several calls.  Ideally I’d be able to mock the calls to HttpClient.PostAsync out, but I can’t because that method isn’t virtual.  The usual way to handle methods like that is to build an interface that I CAN mock out, and then build a wrapper-implementation of that interface which calls HttpClient.PostAsync.  My unit tests would use a mock of that interface, and the real code would use my wrapper.  Adding interfaces adds flexibility to a piece of software, at the cost of readibility and maintainability, so before I went that route I wanted to see if there was a better way.

I came across this post by Gabriel Perez where he shows how to build a fake handler that returns an “injected” response when PostAsync is invoked.  (He credits Glenn Bock for the original source.)  This “russian doll model” as he calls it looked very promising.  In fact, I thought I could even extend it to inject the responses from a queue, allowing me to line them for a specific scenario, and then test my code against it.

I decided that a simple list would suffice for the queue.  FakeHandler would just keep track of which responses it had already handed out:

// FakeHandler, adapted from: http://perezgb.com/2012/02/21/web-api-testing-with-httpclient
        public class FakeHandler : DelegatingHandler
        {
            public List<HttpResponseMessage> Responses { get; set; }
            private int _Index;
public FakeHandler() : base()
            {
                this.Responses = new List<HttpResponseMessage>();
                this._Index = -1;
            }

            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
this._Index++;
                if (this._Index >= this.Responses.Count) { return Task.Factory.StartNew(() => (HttpResponseMessage)null); }
                return Task.Factory.StartNew(() => Responses[this._Index]);
            }
        }

Here is how a test would look using this structure:

        [Test]
        public void SomeTest()
        {
            HttpResponseMessage ConfiguredResponse;
            HttpClient ConfiguredClient;
            FakeHandler NewHandler;
            QueueProcessor MyProcessor;

            // Configure the response.  Set properties (headers, etc.) as needed.
            ConfiguredResponse = new HttpResponseMessage();

            // Build a handler around this response
            NewHandler = new FakeHandler() { InnerHandler = new HttpClientHandler() };
            NewHandler.Responses.Add(ConfiguredResponse);

            // Create a client object around this handler
            ConfiguredClient = new HttpClient(NewHandler);

            // Pass in the pre-configured client to the class under test (dependency injection)
            MyProcessor = new QueueProcessor(ConfiguredClient);

            // Test the method
            var Results = MyProcessor.DoSomething();

            // TODO: Evaluate the results
        }

For “real” use, I would simply pass in a new HttpClient() object to the QueueProcessor constructor.  This all worked quite well to mock out the responses, but my tests could only evaluate what came out at the very end.  I also wanted to make sure the individual responses were being handled properly.

I could have simply injected a set of Asserts into FakeHandler.SendAsync, but I wanted to build it so it could potentially handle completely different tests each time.  To do that, I added an event handler called “OnEntryVerificationMethod”.  This became a property of the FakeHandler class that I could define in my unit test, which would be run at a known point in the execution (on entry), and would have access to both the current and previous responses (see bolded additions below).

// Define the prototype for the delegate that will perform our validation
        public delegate void VerifyOnEntry(HttpRequestMessage CurrentRequest, HttpResponseMessage PreviousResponse);

        // FakeHandler, adapted from: http://perezgb.com/2012/02/21/web-api-testing-with-httpclient
        public class FakeHandler : DelegatingHandler
        {
            public List<HttpResponseMessage> Responses { get; set; }
            private int _Index;

            // Define a delegate that allows me to pass in a custom function at runtime
            public VerifyOnEntry OnEntryVerificationMethod;

            public FakeHandler() : base()
            {
                this.Responses = new List<HttpResponseMessage>();
                this._Index = -1;
            }

            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                // If a custom function was defined, invoke it, passing in the parameters to be verified.
                if (OnEntryVerificationMethod != null)
                {
                    OnEntryVerificationMethod(request, (this._Index < 0 ? (HttpResponseMessage)null : Responses[this._Index]));
                }

                this._Index++;
                if (this._Index >= this.Responses.Count) { return Task.Factory.StartNew(() => (HttpResponseMessage)null); }
                return Task.Factory.StartNew(() => Responses[this._Index]);
            }
        }

I could define this in my unit test using an anonymous function:

            int NumberOfMessagesProcessed = 0;
            NewHandler.OnEntryVerificationMethod = (CurrentRequest, PreviousResponse) =>
            {
                NumberOfMessagesProcessed++;

                if (PreviousResponse == null) { return; }

                switch (NumberOfMessagesProcessed)
                {
                    case 1:
                        // TODO: Perform tests for the first response processed
                        break;

                    case 2:
                        // TODO: Perform tests for the second response processed
                        break;
                }
            };

Now I had a window into FakeHandler’s execution, and could inspect anything I needed.

If HttpClient.PostAsync was virtual (and therefore directly mockable), it would have made testing one call far easier, but trying to simulate multiple calls in a row would probably have pushed me into this structure anyway.

You could argue that in lining up multiple responses like this I’m trying to test too much; that what I should be doing is setting up everything for a given scenario (e.g., responses have already come back as “fail” twice), and then pass in the one I really want to test (the third attempt is a success).  However, I think that would result in a more complicated code base because I would have to make several internal properties available to my test (like the number of times an HttpClient.PostAsync call results in a failure), or make more extensive use of interfaces, or both.  Lining up a series of responses, and then testing that greater scenario, is a more straightforward approach.

Sometimes, I will totally trade having code that is awesomely-flexible and unit test-pure for code that I can more easily get my head wrapped around.

September 5, 2013 Posted by | Visual Studio/.NET, Web API | Comments Off on Queue them up! Unit testing HttpClient

No RSVP required: MvcApplication_BeginRequest and MvcApplication_EndRequest

A few weeks ago I started a new project, and I needed to do some work before and after every request.  It’s a Web API project, so the methods I needed to tap into were MvcApplication_BeginRequest and MvcApplication_EndRequest.

Sounds simple, and usually it would be.  Except that this will be the first project I do in 100% C#.  While I’ve been a polyglot developer for the last few years, I’ve only used C# for the test suites.  VB has been my "goto" language for the actual application (I love language humor).  And while I’ve gotten pretty good at writing in C# and converting between C# and VB, there are still nooks and crannies to C# that cause me to stumble.  How to get ahold of these two event handlers became one of them.

I began with Application_Start.  I figured that would be the place to register the event handlers:

protected void Application_Start()
{
    this.BeginRequest += MvcApplication_BeginRequest;
    this.EndRequest += MvcApplication_EndRequest;

    // More start-up stuff here
}

protected void MvcApplication_BeginRequest(object sender, EventArgs e)
{
    // Do stuff
}

protected void MvcApplication_EndRequest(object sender, EventArgs e)
{
    // Do stuff
}

I hit F5, and was greeted with this error:

10

[NullReferenceException: Object reference not set to an instance of an object.]
    System.Web.PipelineModuleStepContainer.GetStepArray(RequestNotification notification, Boolean isPostEvent) + 25
    System.Web.PipelineStepManager.ResumeSteps(Exception error) +984
    System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +95
    System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +186

Well that’s a new one.  Consulting the internets turned up a couple of posts that showed me where I had gone astray:

http://stackoverflow.com/questions/6590578/how-do-you-wire-up-application-beginrequest-in-asp-net-mvc

http://www.west-wind.com/weblog/posts/2009/Jun/18/How-do-ASPNET-Application-Events-Work

Basically, explicitly adding the event handlers was unnecessary – in fact, it was downright counterproductive.  ASP.NET will find these handlers through Reflection – I didn’t need to wire them up at all.

Incidentally, when I removed the explicit wire-up for this.BeginRequest, but kept the one for this.EndRequest, the error message changed slightly:

20

[NullReferenceException: Object reference not set to an instance of an object.]
    System.Web.PipelineStepManager.ResumeSteps(Exception error) +224
    System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +95
    System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +186

Not the clearest exception messages on the planet, but thankfully this issue only set me back a few minutes.  Onward!

June 28, 2013 Posted by | ASP.NET MVC, Web API | Comments Off on No RSVP required: MvcApplication_BeginRequest and MvcApplication_EndRequest