Flexible, reliable and fast automated testing of ASP.NET Core components with WebApplicationFactory

What if I told you that you there was a way of testing the entire business logic in your web Controller “out-of-the-box”, without having to interact with any of your dependent integrations such as databases or dependent APIs, and still being able to test all the integrated aspects of of your ASP.NET Core component — would you believe me? Well, only if you know about the WebApplicationFactory.
Far too often developers tend to test their Controllers by operating on the classes directly, neglecting the entire aspects of how the Controllers are integrated with the ASP.NET Core run time — this leads to one of the most important part of the component being left untested. The next best thing one might do in this scenario is to create a test server from the test-project manually, and creating a new instance of this for each test, which provides the possibility of testing some parts of the integration. However, this solution is not flexible for testing any scenario in your business logic, as it is not possible to mock or stub your dependent integrations in the code. Additionally, it also brings along slow test-execution times.
Enter the WebApplicationFactory *applause*. The WebApplicationFactory class is a part of the Microsoft.AspNetCore.Mvc.Testing project, and can be referenced as a NuGet package dependency. Microsoft’s summary of this class is “factory for bootstrapping an application in memory for functional end to end tests.”, which I think is an accurate description of the what the class does, and what benefits you get by using it.
The WebApplicationFactory also runs the production code project as a self-containable run time, meaning that it uses all the configuration of the production code itself, and is not dependent on any specific or duplicate configuration in the test-project.
Testing an ASP.NET Core component with the WebApplicationFactory
Let us dig into the code. The project I have built have started out by simply creating a new project in Visual Studio based on the “ASP .NET Core Web Application” template with the “API” selection. This leaves us with the minimum setup for having a running web API, with a default WeatherForecastController class.
In order to illustrate my points in this blog post, I have made some minor adjustments to the WeatherForecastController; I have added a IWeatherForecastService interface with one method, “Get”, and injected the interface into the Controller. If you want to see the code at this point, go to the full commit.
The starting point for our WeatherForecastController looks like this:
Note that “Get” method throws a NotImplementedException at this point, as the examples shown later will apply test-driven development for ensuring that our tests can be trusted.
Now, let us start testing our WeatherForecastController.Get method. First, we need to add the “Microsoft.AspNetCore.Mvc.Testing” NuGet dependency, by adding a PackageReference in our test-project:
Next, we will create a class called “WeatherForecastControllerIntegrationTests” in the test-project, and let the class implement the IClassFixture from XUnit, parameterized with a WebApplicationFactory for our Startup class entry point. This leaves us with a new WebApplicationFactory instance for each test we are running, and the IClassFixture handles the garbage collecting of the WebApplicationFactory instance and all its disposable objects:
Now we can write our first test. The WebApplicationFactory instance let us create an HttpClient for our automatically integrated test-server, by invoking its “CreateClient” method. It is important to know that this method also starts the test-server itself, meaning that it is a costly method to call often. Based on this, I will strongly advice you to create static HttpClient fields for instances that can be used across your tests, and only assign them once in the entire run-time.
We have added a light implementation of the IWeatherForecastService, and injected this as a scoped service in our Startup class. The “CreateClient” method we used for creating an HttpClient for the running test-server simply use the default configuration in our Startup class, meaning that it will inject scoped instances of the WeatherForecastService class in our WeatherForecastController. The first test looks like this:
Note that we assign the HttpClient “_httpClientWithFullIntegration” only once in the entire run-time, so that it can be reused across the tests later, without having to start the test-server running the exact same code several times.
The test checks that the WeatherForecastController.Get method returns a HTTP 200 OK status code with a valid instance of the WeatherForecast class. When running this test it fails on the status code assertion, as it returns 500 InternalServer instead of 200 OK — this is because we have not implemented this functionality in our controller yet. Let us add the necessary code in order for the test to succeed:
The test should now succeed. The next thing we want to test is that if the IWeatherForecast service throws an exception, the method should return HTTP 400 BadRequest with a proper error message. But how can we test this, when all the injected implementation of the IWeatherForecastService does is newing up WeatherForecast instances? This is where the flexible, and arguably the greatest part, of the WebApplicationFactory comes into play.
The WebApplicationFactory provides the possibility of mocking any services in the IoC container of the run time component. This enables the testing of any scenario in your business logic by either mocking or stubbing functionality. In order to test the scenario where the IWeatherForecastService throws an exception, we simply inject a mock of this interface into our IoC container via the WebApplicationFactory. First, we will add the the “Moq” NuGet dependency, by adding a PackageReference in our test-project:
Next, we will mock the IWeatherForecastInterface to throw an exception, and inject this mock instance into the test-server’s IoC container via the WebApplicationFactory:
The _webApplicationFactory.WithWebHostBuilder method sets up a new WebApplicationFactory instance with the specified configuration, and its IWebHostBuilder enables us to call the method “ConfigureTestServices” for overriding the injected services of our web API’s IoC-container. This enables testing of any given scenario of your business logic while still testing the entry point of the web API, which is the HTTP method calls. Our test will currently fail as the functionality for this is not yet implemented, but the following code will make it succeed:
On a side note; I will strongly advice to use an exception filter for handling exceptions in your web API, and this code is added simply for illustrating the capabilities of the WebApplicationFactory.
Final words
The WebApplicationFactory provides a reliable, flexible and fast way of testing ASP.NET Core components.
- It is reliable because it runs the component fully self-contained, and is not dependent on any test-specific configurations, such as duplicating configuration files from the production code
- It is flexible because it enables the overriding of the run time IoC container with mocked or stubbed functionality for each test-scenario
- It is fast because it starts the run time server in an optimized way. It is even much faster if you follow my advice on creating HttpClients that are used across your tests for several scenarios only once during the run time.
If you want to learn more about the WebApplicationFactory and its capabilities, please visit the official documentation.
The full code presented in this post is available on GitHub.

