Functional testing your ASP.NET WEB API
WebAPI
19 Articles
In this article, let's learn about how to do Functional Test
in
WebAPI
in ASP.NET Core.
Table of Contents
Introduction
Functional Testing
ensure that an app's components function correctly at a level that includes the app's
supporting infrastructure
, such as the database, file system, and network
.
The main difference between functional testing and unit testing is that application's infrastructure components like database, file system, etc are
mocked with unit tests
. But with functional testing, we want to ensure that the whole app is working as expected
with all of these components combined together. ASP.NET Core supports functional tests using a unit test framework with a test web host and an
in-memory test server.
Why Functional Testing ?
Functional tests evaluate an app's components on a broader level
than unit tests. Unit tests are used to test
isolated software components, such as individual class methods. Functional tests confirm that two or more app components work
together to produce an expected result, possibly including every component required to fully process a request
.
The characteristics of functional tests include:
- Use the
actual components
that the app uses in production. - Require
more code and data
processing. - Take
longer
to run.
Therefore, limit the use of functional tests to the most important infrastructure
scenarios. If a behavior can
be tested using either a unit test or an functional test, choose the unit test.
Prerequisite
You need to have an ASP.NET Core WebAPI
project. If you don't have one, you can create one from Visual Studio.
We are going to learn this with .NET 8
Web API project.
The default project template contains a WeatherForecastController
. We are going to use this controller for our
functional testing. Here is the API response when we run the project.
Steps to do Functional Testing
Let's see the steps to do functional testing in ASP.NET Core Web API.
Create a
XUnit
Test Project.- Add Package Reference to
Nuget
PackageMicrosoft.AspNetCore.Mvc.Testing
. - Optionally make sure you have
all Nuget Packages updated
to latest version in all your projects. Add
Project Reference to your API project
in your test project.Now we need to expose the implicitly defined
Program class
to the test project by addingpublic partial class Program { }
to the end ofProgram.cs
in Web API.WebApplicationFactory<TEntryPoint>
is used to create aTestServer
for the functional tests.TEntryPoint
is the entry point class of the SUT, usuallyProgram.cs
.We can add
CustomWebApiFactory.cs
in our test project to create a customWebApplicationFactory<TEntryPoint>
. We can thenoverride ConfigureWebHost
method to set the environment toTest
. This is shown in the below code.Code Sample - Custom Web API Factory
That's it we are all set. Now its time to write our first functional test. Let's write a test to check if the API returns the expected response.
We can add a new class WeatherForecastControllerTests.cs
in our test project and add the following code.
Code Sample - First Functional Test
In the above code, we are inheriting from XUnit IClassFixture<CustomWebApiFactory>
and then create
HttpClient
from factory
within our test and make a
HTTP GET
call to weatherforecast
endpoint and deserialize the response
to List<WeatherForecast>
. We are then
asserting
the count of our response. We can also assert the values of the response in the same way.
Note, I'm using XUnit IClassFixture<CustomWebApiFactory>
to create a single instance of the factory for all tests in the class. To learn more
about XUnit's IClassFixture, you can refer to the official documentation
The tests will run in the following flow.
- Start Test Method.
- Create WebApplicationFactory.
- Run Program.cs.
- Service Registration.
- Build Web Application.
- Create HTTP Client.
- Test Code Execution.
Now lets run the test and see the result.
The tests are passing
. We can also write tests to check if the API returns the expected response for different
HTTP methods like POST, PUT, DELETE, etc. in the same way.
Before we wrap up, we can do some additional changes to test code to make it more reusable. The first step is to make a abstract BaseTest class
and inherit
our tests from that.
Code Sample - Abstract Base Test
Now let's adjust our WeatherForecastControllerTests
to inherit from BaseTest
and use the HttpClient
from BaseTest class
as shown below.
Code Sample - Functional Test Inherited from Base Test
Good. Now we can do final improvement which is to assert
the Http Status Code
of the response and move deserialization and error logging
using ITestOutputHelper
into a separate HttpClientExtensions class
. This small investment will help us to write more tests easily in the
future.
Code Sample - Functional Test HttpClientExtensions
Now we can use the HttpClientExtensions
in our tests as shown below.
Code Sample - Functional Test with BaseTest and HttpClientExtensions
Now lets run the test and see the result.
Summary
In this article, we learnt about what is funtional test and how to write functional test in ASP.NET Web API. Functional test help us to test
end to end functionality of our application without mocking any infrastructure dependencies
. This is very useful
to test the application in real world scenario. In our next article we will learn about how to do functional testing in ASP.NET Web API with database.