ASP.NET Core 5 & EntityFramework Core: Clean, clear and fluent integration tests with Calzolari.TestServer.EntityFramework, FluentAssertion.Web and xUnit (2024)

2021-04-17 by anthonygiretti

Introduction

Not long ago I was asked to do integration tests with ASP.NET Core and Entity Framework Core and I was confronted with some difficulties, in particular the fact of testing Entity Framework Core in integration? I have not found a simple tutorial to create clear and simple tests and especially how to get around the limitations of Sql in memory when using EntityFramework Core. So I had to find work arounds with SqlLite to do my tests while making sure that there are no data collisions in each test. In addition, I wanted to make sure that I was using AAA (Arrange, Act, Assert) in such a way as to maintain optimal ideal readability. So I had the idea to create the Calzolari.TestServer.EntityFramework library which encapsulates all the management of EntityFramework Core in integration, this library also uses Flurl for writing Http clients in a fluid way and FakeBearerToken allowing to pass tokens in the simplest way in endpoints protected by JWTs. In this article I will also show how to use Calzolari.TestServer.EntityFramework in conjunction with FluentAssertions.Web which is an assertion library for the web and xUnit in order to perform really clean integration tests! I used as well AutoFixture to facilitate somme Arrange.

Note that Parallelism MUST BE deactivated while testing, the database is created and removed after each test which avoids any data collision, the DbContext is reinstancianted between each test. It’s not recommended for large databases.

Test scenario

We’ll consider the following scenario, an endpoint protected by a JWT which gets a country by its Id, and the second one protected with a JWT that must contains the Admin role which creates a country:

Setup your integration test project

Install first the following packages, for example in command line in the Package Manager console:

Install-Package Calzolari.TestServer.EntityFrameworkInstall-Package AutoFixtureInstall-Package FluentAssertions.WebInstall-Package xunitInstall-Package xunit.runner.visualstudioInstall-Package Microsoft.AspNetCore.Mvc.TestingInstall-Package Microsoft.NET.Test.Sdk

Don’t forget to import as reference the ASP.NET Core project you want to test.

Create a dedicated Startup.cs file for your integration tests

I strongly suggest to create specific Startup.cs file (name it TestStartup.cs for example) for better clarity, don’t use the Startup.cs file from the web project you want to test.

Then :

  • Add the methodAddApplicationPartwhich takes in parameter any class of your webapplication (for example the Startup class), this is needed to retrieve controllers and register them in the integration test project
  • Register the DbContext with the following method:AddIntegrationTestDbContext, this is needed for integration test to be working with EF Core, behind the scene it register your DbContext with SQLite Database
  • Register the fake bearer token authentication with the AddFakeBearerToken method, this is needed to create an identity with a fake token while performing integration tests

It should look like this:

Create a Web factory to create the test server

Inherit from FlurlWebFactory, generic T can be any class of your webapplication (for example the Startup class, the reason why is explanied in a previous post here: ), then overrideCreateHostBuilderand use your TestStartup.cs file like this:

Create a xUnit collection definition

A collection definition allows injection dependency (Singleton lifetime) within your test classes. The following example shows how to register a collection named “AssemblyFixture” that allows to pass into your test classes the TestFactory we defined just before:

Create a base test class

Inherit from IntegrationTestBase<TDbContext, T>, TDbContext is your DbContext and T is the same class that you defined as generic parameter on FlurlWebFactory when you wrote your web factory, then, add [Collection(“AssemblyFixture”)] attribute on your base test class. This is here where you can add AutoFixture or anything else that you need for your all your tests. Your base test class should look like this:

Write your tests

Create a test class and inherit from the base test class. Pass the web factory by injection dependency and write your tests. I suggest to useFluentAssertionsfor your assertions

To feed the database use the method Arrange like this

var countries = Fixture.Build<Country>() .CreateMany(3); Arrange(dbContext =>{ dbContext.Countries.AddRange(countries);});

If you expect an auto incremented Id, it’s filled automatically like this:

var country = Fixture.Create<Country>();Arrange(dbContext => { dbContext.Countries.Add(country); });// country.CountryId CountryId is filled

Create a fake token to be authenticated while calling the endpoint to test, sub is the claim that represents the identity within a JWT:

var token = new{ sub = "Anthony Giretti"};

Then call your System Under Test (SUT):

var response = await BASE_REQUEST.Route(BaseRoute).FakeToken(token).GetAsync();

And assert the result by using FluentAssertions.Web:

response.ResponseMessage.Should().Be200Ok().And.BeAs(countries);

The response is typed as IFlurlResponseMessage, whichs exposes the native HTTP ResponseMessage , that’s why I had to write response.ResponseMessage to get the HTTP response.

The test class should look like this:

You can find more example here, especially with Authorization based on Roles on a POST endpoint:

Conclusion

This post aimed to show how you could test your ASP.NET Core application which uses EntityFramework Core, as you can see, all the complexity brought by EntityFramework Core in integration testing has been encapsulated. Don’t forget it’s not recommanded for larage database, on my end, I’m testing my microservices like this.

I hope you liked this post, and if you have any suggestion, for example, adding new features in Calzolari.TestServer.EntityFramework, feel free to send me an email :).

Related posts

ASP.NET Core 5 & EntityFramework Core: Clean, clear and fluent integration tests with Calzolari.TestServer.EntityFramework, FluentAssertion.Web and xUnit (2024)

References

Top Articles
Latest Posts
Article information

Author: Margart Wisoky

Last Updated:

Views: 5880

Rating: 4.8 / 5 (78 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Margart Wisoky

Birthday: 1993-05-13

Address: 2113 Abernathy Knoll, New Tamerafurt, CT 66893-2169

Phone: +25815234346805

Job: Central Developer

Hobby: Machining, Pottery, Rafting, Cosplaying, Jogging, Taekwondo, Scouting

Introduction: My name is Margart Wisoky, I am a gorgeous, shiny, successful, beautiful, adventurous, excited, pleasant person who loves writing and wants to share my knowledge and understanding with you.