End-to-end Integration tests for Web Api

Recently I was looking at the NancyFx framework, what found I liked most about the whole thing was the Nancy.Testing library. It allows you to not just test the code inside your API, but actually make the request to the Url, with any headers, body or whatever with it. This means you are testing everything. You can ensure you are sending back the right status codes, content types and that you are handling authorization correctly.

To do this in Nancy, the code looks something like:

 

[TestMethod]
public void GetEmployeesExpectOK()
{
    var bootstrap = new ConfigurableBootstrapper(c => c.Module<EmployeeModule>());
    var browser = new Browser(bootstrap);

    BrowserResponse response = browser.Get("/Employees/", with =>
    {
        with.HttpRequest();
        with.Header("Accept", "application/json");
    });

    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}

 

As you can see here, you create a “Browser” and use it to request at the specified route. Pretty cool. This was particularly useful for adding some automated acceptance tests for your application – as it allows us to tests all the way from an API request, down to the data storage and back out again. However, we were not using NancyFx for our API, we were using ASP.Net Web API instead – so we needed to replicate this way of testing.

Happily a library exists which allows you to implement tests this way for Web API. This is called WebApi.Testing (http://www.nuget.org/packages/WebAPI.Testing/). The code is very similar, except there are some flaws.

 



[TestMethod]
public void GetEmployeesExpectOK()
{
    var config = new HttpConfiguration();
    config.MapHttpAttributeRoutes();
    config.Routes.MapHttpRoute(
    name:"DefaultApi",
    routeTemplate:"api/{controller}/{id}",
    defaults:new{ id =RouteParameter.Optional});

    Browser browser = new Browser(config);var response = browser.Get("/Employees/",(with)=>
    {
        with.Header("Accept","application/json");
        with.HttpRequest();
    });
    Assert.Equals(HttpStatusCode.OK, response.StatusCode);
}

What I don’t like about this is that we have to re-define the routes for the API project, so we’re not really testing the real routes from our application, which is a shame. The solution we found was to edit the WebApiConfig in the API project, so we can get the routes from out test, like so:


public static void Register(HttpConfiguration config) 
{ 
    // Setup Web API configuration routes 
    config = GetConfig(config); 
} 

//This is added so we can return the HttpConfiguratio
public static HttpConfiguration GetConfig(HttpConfiguration config) 
{ 
    config.MapHttpAttributeRoutes(); 

    config.Routes.MapHttpRoute( 
    name: "DefaultApi", 
    routeTemplate: "api/{controller}/{id}", 
    defaults: new { id = RouteParameter.Optional } 
    ); 

    return config; 
}

Then in the test class:


[TestMethod]
public void GetEmployeesExpectOK()
{
    var config = ApiProject.WebApiConfig.GetConfig(new HttpConfiguration()); //Get the routes from API project
    var browser = new Browser(config); 
    var response = browser.Get("/Employees/", (with) => 
    { 
        with.Header("Accept", "application/json"); 
        with.HttpRequest(); 
    }); 

    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}

As you can see here, we just get the route configuration from the application and use it in the test, and now we are testing the routes too.

One thought on “End-to-end Integration tests for Web Api

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

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

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s