C#, WebApi

Testing a WebAPI in .NET Core with Integration tests

3 min read

NOTE: This posts targets ASP.NET Core 2.X. If you are looking for ASP.NET Core 3.1, see my repository. I’ve also made a NuGet package for easier consumption.

You finished developing your API, and you are ready and eager to push it to production. You then realize that you are missing some tests to make it a real production ready API.

Lucky for you, ASP.NET Core 2.X provides us with an In-Memory HTTP Server (TestServer) to help us achieve this.

This post aims to help you write end to end tests (e2e) using ASP.NET Core 2.1 (and possibly future versions!) in order to test the flow of your API. Remember that having tests in place, whether they are unit or end to end, helps you to achieve good continuous integration (CI) and continuous deployment (CD)

In this post, we will use the following libraries:

xunit
FluentAssertions
Microsoft.AspNetCore.Mvc.Testing
Microsoft.NET.Test.Sdk

Setup

Mimicking Startup class

Unless your Startup class is very simple, in this case you can use it as-is, the first step is to create a TestStartup class that mimics your actual Startup class (entry point) in your project. This class should be a lightweight version that contains only the necessary stuff for your API to work. Remember to replace all underlying physical services, such as your distributed cache, to in-memory alternatives.

This class should have the same methods that you see in your Startup class respectively:

ConfigureServices(IServiceCollection services)
Configure(IApplicationBuilder app)

WAIT! My API is protected with JSON Web Tokens (JWTs) through the Bearer authentication type

Thanks to GestionSystemesTelecom, they forked the JwtBearer security module from ASP.NET Core and cleaned it up to fake the JWT auth. You can get their library here.

Remember, as this library is just a fork of the JwtBearer library to simplify testing, you still need to set the fake token on the authorization header when calling the API as shown below.

Note that I’ve forked this library to incorporate the InboundClaimsMapping behavior from the JwtBearer library so that it follows the actual JWTBearer behavior. This library does not handle that.

UPDATE 2019-08-07: I’ve forked and enhanced the libary with what i’ve mentionned above. You can see the code in my GitHub repository here.

Creating a factory class

The second step is to create a factory class that we will use to create the Server and the HttpClient(s) to consume your API.

Create a class that derives from WebApplicationFactory<T> where T is your TestStartup class and override the following methods:

IWebHostBuilder CreateWebHostBuilder()
void ConfigureWebHost(IWebHostBuilder builder)

Here’s an example of what such class can look like:

You are not obliged to create such factory class and you may use WebApplicationFactory<T> directly in your test classes. You will, however, need to do additional configuration in your test class constructor. The idea behind deriving from this class is to lighten the implementation of your test classes and keeping only (or as much as possible) what is needed to test.

What is the WebApplicationFactory class?

The WebApplicationFactory class as described in the docs is a factory for bootstrapping an application in-memory for functional end to end tests. This factory can be used to create a TestServer instance using the MVC application defined by an entry point (Startup class) and one or more HttpClient instances used to send HttpRequestMessage to the TestServer.

Writing our first test

It is now time to write our first test. Your test class should always be, at a minimum, composed as such:

I’m using here the IClassFixture from xunit, as I want to create a single test context and share it among all the tests in the class, and have it cleaned up after all the tests in the class have finished. That is because I want to create 1 TestServer for all my tests. You can read more about this concept in the xunit documentation.

First test

The first test will test that our method Get in our controller (testsdemo) returns the proper status code and content-type. The Get method looks as follow:

I’m using a xunit theory here as I may want to test multiple routes (inlineData attribute), but for the sake of this example, I am using only 1 route

Conclusion

You should now be able to create end to end tests for your API. Make sure to stay tuned as in my next post, I will show you how you can test your SignalR endpoints using this method.