Running integration tests for ASP.NET Core apps
One of the things I really disliked about the previous versions of ASP.NET is that there's no real good way to run integration tests on your web application. You basically have to set up a full webserver to run integration tests.
Of course if you use Web API 2 or MVC 5 you have the official testhost. It solves a lot of problems, but the API is a mess to work with and very inflexible.
The story for ASP.NET Core is quite different. You can now do a lot more in your testcode and it's a lot easier to set up. Let's take a look at what integration testing in ASP.NET core looks like. <!-- more -->
Setting things up
Setting up an integration test for ASP.NET core starts by creating a new project. You can do that from Visual Studio, but I like the commandline better for setting up test projects.
When you run
dotnet new -t xunittest you get a fully configured Xunit project with a sample test.
If you set up your project in Visual Studio you have to do the same set up by hand. That's why I like
the commandline better at the moment.
The project.json looks allright, but when you try to restore your packages you well get a few warnings.
This is to be expected, because the .NET Core test runner for Xunit is still in preview.
xunit packages to get rid of the warnings.
To write an integration test you need the
Microsoft.AspNetCore.TestHost package. Add this to your project.json
dotnet restore or wait for Visual Studio to download the package for you.
Write your first test
Now that the project is set up you can write your first integration test. The structure of an ASP.NET Core integration test looks like this:
First you need to create a new
TestServer instance. It needs access to a
which is pretty much the same thing as you will find in your
WebHostBuilder is responsible for configuring your application. You can call
various methods on it to configure your web app. The simplest thing is to call
UseStartup on it and supply your
Once you have a test server you can start to perform requests. For this you
CreateClient which returns a new
HttpClient instance that is
configured to talk to your test server.
Now that you have a test client you can send requests to the server and verify the results coming back from the server.
Mocking stuff out
The current setup fires up the whole API/Web application that you're testing. This may or may not be what you want. Sometimes it can be useful to mock out a few things in your test.
For example if you are talking to WCF services you may want to mock out the agents for them. You could spin up your WCF services, but that would make the test rather large.
Instead you can modify the services of your application by adding additional lines to the web host builder.
When you invoke
ConfigureServices you can configure custom services for your application.
Within the action or method that you provide it, you can replace services or add additional services.
In the sample above I registered a mock using
Moq instead of my regular WCF agent.
Notice: Services that you provide here are added before the services that are configured in your startup class.
In order to make the mocks functional you do need to change your
ConfigureServices method in the startup class.
Instead of calling
AddTransient you need to call the
TryAdd... variant of
the class that you want to replace in your tests.
TryAdd... methods instead of the regular registration methods doesn't change anything at runtime.
It just means that when a service was registered before it won't be replaced by the one you add it again.
If you use the regular
Add... methods you will overwrite your test services.
ConfigureServices in the startup for the sample above will look like this:
WebHostBuilder class can do other stuff besides replacing services as well.
One very cool feature is that you can supply custom configuration for your application.
In order to configure custom settings you need to invoke the
To use the method you need to supply a key and a value for your setting.
The custom settings are applied after the standard ones. This means that when you specify
a setting in your test it will override the ones loaded by the
And there's loads more
TestServer class uses the
WebHostBuilder to construct your web application
it's quite flexible in what you can do. All the normal stuff that you'd normally do in your
Program.cs file can be done in your test as well.
This means that there's a lot more you can do in your integration test than what I've written down here. So get out there and explore your options and have fun!