Skip to content

Testing .NET Core WebAPI with TestServer

Why is TestServer useful?

I am of the opinion that the best way to unit test and to TDD the functionality of your ASP.NET Core WebAPI, is to use in memory TestServer. Actually, since an in memory HTTP test server is used, we can call these tests as “semi-integration” tests, but their characteristic are the same as for unit tests: they can be executed without a need of external dependency. And believe me, it is a real deal when we talk about testing an API endpoint. With just a normal plain old unit tests, we would need to mock out the API controller dependencies and to test and verify what happens when a controller method is invoked. These kind of tests can have surely their benefits, but sometimes we want to test other characteristics of our API, such as endpoint route-names, parameters and payload deserializations. Let’s see how we can achieve it by using TestServer.

Set up a testbase

In order to set up an in memory HTTP Test Server we need to use an official Microsoft .NET class called TestServer. To get access to this class, the following nuget package must be installed:


Once the package is installed, we can start write our unit tests using our in memory TestServer. This server can create an HttpClient for us, that can be used to issue HTTP requests to our WebAPI. How cool is that?

In order to create a TestServer instance, we need to configure a WebHostBuilder first. With this builder class we can configure many properties of our TestServer, such as content root path, used Startup and other service configurations. First of all, let’s see how we can set up a TestServer:

Then let’s see how the corresponding production code looks like:

Testing HTTP GET

We already have our testbase set up and we have our functionality implemented within an API Controller. Now it is time to write our tests!

Note that only for the sake of presenting the usage of TestServer we write our unit tests afterwards. In real solutions it is highly recommended to write your test before the corresponding production code and to follow the Test Driven Development design practice.

For testing purposes I use additional packages such as:

  • XUnit – a test runner for test execution;
  • Moq – for mocking up external dependencies, such as data layer concerns;
  • NFluent – an awesome fluent library for fluent test assertions.

The unit test looks as the following:


  • On the “Arrange” part we mock our repository returning some fake products;
  • On the “Act” part the client is created and we call our API endpoint with GET HTTP method;
  • Finally, the expected results are checked and verified.


Not it is our time to write some tasty test for endpoint “api/products” with calling it with HTTP Method type POST:


  • On the “Arrange” part we create a HTTP body in json for creating a new product in our system;
  • On the “Act” we send this payload to the endpoint as a POST request;
  • Finally, we verify if the new product is persisted in the data layer via our repository.

Further functionalities

Of course, next to GET and POST requests, it is also possible for fire requests with HTTP method type DELETE, PATCH and PUT, covering all the basic and most popular request types. For more info about these kind of integration tests, please read the official documentation.

Published inTesting

Leave a Reply

Notify of