Automated Testing
We are very much infavour of automated testing and currently have 2 levels of Automated Tests:
Unit Tests
Integration Tests For more info please see below:
Unit Tests
We use unit test to test functional business, these test will often use a mocking framework (currently Moq) to mock dependencies so that we can focuss on testing the behaviour of the class / method under test. We make use of the xUnit unit testing framework for ochestrating our tests.
Integration Tests
Alongside our unit tests we also have a large number of Integration Tests, mostly for our APIs. These test make use of the Microsoft.AspNetCore.Mvc.Testing framework to spin up a test host for the API, which can then be called and tested. We also back these tests with a Sql Database with is hosted in Docker and has the migrations applied. Each test is responsible for creating its own initial data in the database and we use the Respawn library to reset the DB after each test.
Our implementation
NOTE: Before you start, you will need to run an instance of SQL in Docker. You can use the sql-server-docker-compose.yml file for this.
If you look at the FourDBS.UnitTests project in the Api\Framework folder you will see the following files:
ApiBaseTest- A base class for all Database backed integration tests (typically API tests). It contains functions for initialising the DB and has helper properties for accesing the DB.ApiCollection- An xUnit Collection class which is used on theApiBaseTestclass above.ApiOrDbBackedTestApplication- This implements microsoft'sApiOrDbBackedTestApplicationclass which is part of theMicrosoft.AspNetCore.Mvc.Testinglibrary, and overiddes the WebHost program class. This class initialises the SQL DB, creating it if necessary and running, allows the overriding of configured services and config, essentially it allows you to hook into various methods in the aspnet start up pipeline.DataInitialisationHelper- A helper class that we have created to help with resetting the Database between tests and executing migrations.HttpClientHelper- A helper class for calling API's in the various tests and deserializing results.TestConnectionStringProvider- in our code we use a connection string provider to get a connection string for Entity Framework and/or NPoco. This is an implemenation the we use to overried the standard provider, so that the data access code points at the test DB.TestDbHelper- Additional functionality for creating / drop / checking availability for the test database.
Creating and API or DB Backed Integration Test
To creat an integration test, use the following syntax:
Further reading
For more info see:
For the future
We should investigate using Test Containers, also see: Integration Test In Asp.Net Core 6 Using SqlServer Image and TestContainers.
Testing tips
Below are some tips for unit testing with xUnit.
Using Theories
As specified in our best practice document, using Theories can simplify our tests and save lines of code. For more information on using Theories, see: xUnit Theory: Working With InlineData, MemberData, ClassData.
One short coming of Theories is that it can lead to methods with larger parameter lists, e.g.
The good news is that there is a way to pass complex types into Theories (though you will struggle to find it documented). Using this technique, the above method could be refactored into: