Category Archives: Testing

Web API Unit Tests: Get HttpResponseMessage from IHttpActionResult

This is a quick post to share a pattern for unit testing Web API methods where async Task<IHttpActionResult> is being used as the return type.

Download the example project

During a recent code review of some unit tests for a Web API project, a stylistic issue was picked up that was pretty minor but appeared through most of our controller tests. Here’s the kind of thing we were seeing:

// Unit test excerpt...
var result = await controller.GetSomethingAsync(123);
Assert.IsNotNull(result); // Check the result isn’t null
var someResult = result as OkNegotiatedContentResult<SomeModel>; // Cast as Ok<SomeModel>
Assert.IsNotNull(someResult); // Check the cast worked

There’s nothing technically wrong with this since it verifies that we’re getting back an expected result when we call GetSomethingAsync with a value of 123. What is doesn’t do so well is express the semantics of what’s being tested. Here’s the above code as a list of pseudo-code steps:

  • Get the result of the method when called with “123”
  • Check it returned something
  • Try to cast the result to the type we’d expect if everything went okay
  • Check the cast worked

It’s those last two steps that we didn’t like. As test-driven developers, we prefer small, discrete steps in tests that help us to see precisely what’s failed when things break; as Web API developers, we prefer to view our APIs in terms of HTTP rather than abstractions. What we wanted to test might better be written as:

  • Get the response from calling the method with “123”
  • Check we have a response
  • Check that it’s an HTTP 200/OK response
  • Check that the content is as we expect

While we could have changed the return types in all our API methods from IHttpActionResult to HttpResponseMessage to achieve this, we really just wanted a way to treat the existing return types as HTTP responses. This turns out not to be trivial, though, as the HTTP response is built in a pipeline as part of an HTTP request, along with its headers, status, etc. A little digging around in the ASP.NET MVC unit tests yielded some examples of how to do just enough mocking around the ApiController to build the HttpResponseMessages in a unit test environment. Furthermore, by presenting it all as a single extension method, any additional complexity in the unit tests is kept to a minimum.

Here’s what the previous code excerpt looks like using the new approach:

HttpResponseMessage response =
    await controller.WithMockedHttpRequest(c => c.GetSomethingAsync(123));
Assert.IsNotNull(response); // Check we have a response
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); // Check the HTTP status
SomeModel someModel;
Assert.IsTrue(response.TryGetContentValue(out someModel)); // Check the content

The new method, WithMockedHttpRequest, is an extension method defined as follows:

public static class TestExtensions
{
  /// <summary>
  /// Runs the controller action within a mocked HTTP context
  /// </summary>
  /// <typeparam name="T">The controller type</typeparam>
  /// <typeparam name="TReturn">The controller action return type</typeparam>
  /// <param name="controller"></param>
  /// <param name="func">The controller code to execute within a mocked HTTP context</param>
  /// <returns>The HttpResponseMessage containing the action result</returns>
  public static async Task<HttpResponseMessage> WithMockedHttpRequest<T, TReturn>(
    this T controller, Func<T, Task<TReturn>> func) where T : ApiController
  {
    // Build a mocked JSON request/response configuration
    MediaTypeFormatter expectedFormatter = new StubMediaTypeFormatter();
    MediaTypeHeaderValue expectedMediaType = new MediaTypeHeaderValue("text/json");
    ContentNegotiationResult negotiationResult = new ContentNegotiationResult(expectedFormatter, expectedMediaType);
    Mock<IContentNegotiator> contentNegotiator = new Mock<IContentNegotiator>();
contentNegotiator
      .Setup(n => n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(), It.IsAny<IEnumerable<MediaTypeFormatter>>()))
      .Returns(negotiationResult);
   using (HttpConfiguration configuration = CreateConfiguration(new StubMediaTypeFormatter(), contentNegotiator.Object))
    {
      controller.Configuration = configuration;
      // Build a mocked request context from which to build the response
      using (HttpRequestMessage request = new HttpRequestMessage())
      {
        controller.Request = request;
        var actionResult = await func.Invoke(controller);
        // Create the response from the action result
        if (typeof (IHttpActionResult).IsAssignableFrom(typeof (TReturn)))
        {
          return await ((IHttpActionResult) actionResult).ExecuteAsync(CancellationToken.None);
        }
        else
        {
          return await Task.FromResult(request.CreateResponse(actionResult));
        }
      }
    }
  }

  private class StubMediaTypeFormatter : MediaTypeFormatter
  {
    public override bool CanReadType(Type type)
    {
      return true;
    }
    public override bool CanWriteType(Type type)
    {
      return true;
    }
  }

  private static HttpConfiguration CreateConfiguration(MediaTypeFormatter formatter, IContentNegotiator contentNegotiator)
  {
    HttpConfiguration configuration = new HttpConfiguration();
    configuration.Formatters.Clear();
    configuration.Formatters.Add(formatter);
    configuration.Services.Replace(typeof(IContentNegotiator), contentNegotiator);
    return configuration;
  }
}

The example is based in part on the ASP.NET MVC unit tests for ContentNegotiatedResult. Those tests are a good place to start if you want to get a feel for how the HTTP responses are built.

– Mike Clift

Avoid embarrassment. Perform testing.

This was originally going to be a post about the evolution of the IT department and how if we wish to stay employed and interested in our jobs we must move along with the rest of the industry.

Then an email arrived in the inbox of a colleague.

First some background. As you can see from my linkedin profile (I hate those things too; unfortunately until I write more blog posts it’ll be essential to my ongoing employment). I’ve recently started working at The Royal Society of Chemistry after a few years owning and running a small IT Consultancy.

As a provider of services when I worked for Avanade, IBM & myself I adopted a number of provider <-> client behaviours that I believe should be adopted by all IT departments, one of these was performing managed testing, and handing over both the results and testing to the customer.

I’ll assume that if you’re reading this blog you’re familiar with a software development lifecycle and software testing. I see testing like this:

  • Does this unit do what I want it to do (unit testing);
  • Does this requirement do what we think you want it to do (system testing);
  • Does it do what it used to do (regression testing);
  • Does it do what you want it to do (acceptance testing).

Sometimes we merge these (I’m thinking system and regression) and sometimes we do them informally. But we should do them before moving from one stage to the next. Sometimes we do additional types of testing (load testing, integration and penetration) but we should be doing the four types of testing above.

As a provider of services; when my team (or sometimes just me!) handed something over to a customer we wrote a test plan and executed any tests we thought appropriate. Broadly though, the test plan included manual and automated tests which covered every area of the application. Your requirements help to identify the areas.

Sometimes it was: Click here, do this, install this framework does it still work, uninstall that, does it still work?

Sometimes it was: Does this web service return this result.

It depended on the requirements.

In short though, we had a test plan we created tests and we executed those. We then passed this over to the customer when testing was completed.

Yes. We hand it all over. The tests, what failed, how many bugs, how many cycles. Everything. My main reason for doing this initially was a feeling that the data belonged to the customer. We charged them to create it, we executed it, they owned it.

I must admit, I didn’t think of that as being revolutionary or some extraordinary insight. I still don’t think it is. But if you’re not doing this today for your customers you should be. As I said, they paid for it and it’ll help get them feel a sense of ownership for the product (which they should have!) as well as show how a third party can add value – those tests are a gold mine of useful information for regression, future requirements, and user manuals.

This brings me back to that email that arrived in the inbox of a colleague that prompted this blog post and a slightly ranty tweet.

My colleague (a .NET developer who’s moving into a more TA/BA role, it’s all very woolly) has been working with a third party developer to create a new application which is going onto our website. We’ve spent a fair bit of cash on this, and they have charged us for 30+ days of system testing.

It arrived, and it didn’t work.

Despite the test plan being charged for, and also being someone to execute tests (30+ days!) they state “we only provide unit test” and “you’re the quality gate”

Not acceptable. While I’d never advocate going from supplier to production, I expect the application to hang together and meet the broad set of requirements we’ve provided (or if you’re the supplier the requirements that have been provided to you.)

If you’re an IT department you should be behaving in this way already. If you’re an IT department using a third party supplier you need to make sure these steps are performed before letting your users near any new application. Allow time to do it and allow time to check up on your suppliers.

Now, all I have to do is convince the business that they should be the owners of the test plan.

– Alan Smith