An easy way to write an integration test with Web API

Jul 23, 12 • In WebAPI

In my previous post I wrote about the Self-Host in Web API and why this features is so cool. In this I’d like to show how easy is to create an integration test with Web API (with my base class of course :) ).

Before to proceed is important to understand because it’s important to create an integration test.
I think this is a good point and the answer is not so easy but I’ll try to explain my point of view.

In most environments (including ASP.NET MVC) integration tests are expensive because you need a webserver, configure it for each test and so on.

With Web API you don’t have this issue, there is the Self Host that helps you. A good point for the integration test is that you can replicate a real situation and, for the Web API, you can test the content negotiation, authentication and other important features.

The recipe for this test includes:

  • xUnit (is not mandatory but actually it’s my favorite test framework);
  • SharpTestEx (is an incredible cool library wrote by my friend Fabio Maulo);

The problem of the integration test is the repetitiveness code, in fact you have to create the server, configure it, make a request and so on.

For this reason I created a base class that helps us for this job and the result is pretty awesome.
In this example I want to test the Action below:

public class ValuesController : ApiController
{
  public IEnumerable<string> Get()
  {
    return new[]
             {
               "http://tostring.it", 
             "http://imperugo.tostring.it",
             "http://twitter.com/imperugo",
             "http://www.linkedin.com/in/imperugo"
             };
  }
}

And the unit test should be like that:

[Fact]
public void ValueController_WithGetMethos_ShouldReturnValidData()
{
  HttpSelfHostConfiguration configuration = new HttpSelfHostConfiguration("http://localhost:8080");
  configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
  configuration.Services.Replace(typeof(IAssembliesResolver), new WebApiClassBase.TestAssemblyResolver(typeof(ValuesController)));
  configuration.Routes.MapHttpRoute("Default", "{controller}", new { controller = "Home" });

  HttpSelfHostServer server = new HttpSelfHostServer(configuration);
  try
  {
    server.OpenAsync().Wait();

    var request = new HttpRequestMessage();

    request.RequestUri = new Uri("http://localhost:8080");

    request.Method = HttpMethod.Get;

    var client = new HttpClient(server);
    using (HttpResponseMessage response = client.SendAsync(request).Result)
    {
      response.Should().Not.Be.Null();
      response.IsSuccessStatusCode.Should().Be.True();

      string[] result = response.Content.ReadAsAsync<string[]>().Result;

      result.Length.Should().Be.EqualTo(4);
      result[0].Should().Be.EqualTo("http://tostring.it");
      result[1].Should().Be.EqualTo("http://imperugo.tostring.it");
      result[2].Should().Be.EqualTo("http://twitter.com/imperugo");
      result[3].Should().Be.EqualTo("http://www.linkedin.com/in/imperugo");
    }
  }
  finally
  {
    configuration.Dispose();
    server.Dispose();
  }
}

This code has several problems; the code is not so easy to read, not maintainable, it’s repetitive, etc.
I wrote a base class that reduce and improve the test dramatically and the result is this:

public class ValuesControllerTest : WebApiClassBase
{
  public ValuesControllerTest() : base("localhost", 8080, typeof (ValuesController)) { }

  [Fact]
  public void ValueController_WithGetMethos_ShouldReturnValidData()
  {
    base.Start();

    var response = base.CreateRequest("/Values", HttpMethod.Get);

    response.Should().Not.Be.Null();
    response.IsSuccessStatusCode.Should().Be.True();

    string[] result = response.Content.ReadAsAsync<string[]>().Result;

    result.Length.Should().Be.EqualTo(4);
    result[0].Should().Be.EqualTo("http://tostring.it");
    result[1].Should().Be.EqualTo("http://imperugo.tostring.it");
    result[2].Should().Be.EqualTo("http://twitter.com/imperugo");
    result[3].Should().Be.EqualTo("http://www.linkedin.com/in/imperugo");
  }
}

I replicated the same test but in a more elegant way. The only important things to remember are in the constructors:
The first parameter is the host, the second one the port and the last one is the type of the controller to test.

Obviously the class is not complete and more features will come, but now you can override the configuration so you can configure the Routing and other important parameters.
If you like this approach and you want to use or extend my base class, you’re welcome to do it here!

Related Posts

  • http://twitter.com/bradwilson Brad Wilson

    Nice, but it will be faster (and won’t require admin rights) if you use the in-memory HttpServer instead of the WCF self-host server.

    • http://www.tostring.it/ Ugo Lattanzi

      Hi Brad,
      you r right. I’m playing/testing with Web API. And the admin rights are is frustrating.
      Maybe I’ll extend my class using the in-memory HttpServer and I’ll write in the next post.

      Thx for the advice and for the comment
      .u

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1152

  • Kori

    Hey, will you make the source available for the base class?

  • Cristiano Degiorgis

    Great tips! We are using same approach w webapi and it really makes our acceptance tests so much easier… I’m glad web api interest is growing. We are using the framework since 1 year. We are currently relying on prev 6. I’ll be glad to have a chat w/ you sharing our experiences.

    • http://www.tostring.it/ Ugo Lattanzi

      Hi Cristiano,
      sure why not. Write me an email here http://tostring.it/contact/ and I’ll forward you my skype account ;)

Scroll to top