Unit Testing ASP.NET Web API by Mocking DbContext with NSubstitute
- By : Mydatahack
- Category : .NET, Web Technologies
- Tags: ASP.NET, FluentAsserstions, NSubstitute, Unit Test, Web API
In the previous post, we created a simpleWeb API in 5 minutes. Now, let’s refactor the code so that it is unit testable with xUnit.
The API we build previously was sourcing the data from MySQL database through DbContext. This is an external dependency that we need to replace in the unit test. There are a few good mocking libraries available for.NET. Here, we are going to use NSubstitueto mock the DbContext.
Code Refactoring
(1) Extract Interface from sakilaDbContext
The rule of thumb with NSubstitue is to mock interfaces, not classes. In the Actors API, we have the DbContext class called sakilaContext. We first need to extract the interface from the DbContext so that it can be mocked.
This can be done easily with Visual Studio by right clicking the class name in sakilaContext, choose Quick Actions and Refactoring, and then select Extract Interface.
(2) CreateActorsRepository.cs
Let’s move the logic to get actors from the controller and handle it with ActorsRepository and extract the interface. In this way, our unit test runs against the repository not the controller. The controller simply uses the interface, IActorsRepository class to get all the actors.
First, create a folder called Repositories, add ActorsRepository.cs and extract the interface. In the repository, we inject the dependency on IsakilaContext. If you need more information on dependency injection, read here. Understanding Inversionof Control also helps you to make your code more robust and unit testable.
(3) UpdateActorsController to use ActorsRepository.
Let’s refactor the controller so that it uses the logic from ActorsRepository to get data. In this way, the controller is only responsible for receiving the request and returning the response and the core API logic sits in the repository class.
Creating Unit Test
After refactoring your code, it is ready for unit testing. Let’s set up the test project and write test code.
(1) Add xUnitTest Project, Configure Project Dependencies and Install NSubstitute
First of all, you need to create a test project by adding xUnit Test Project under the solution. The naming convention is the project name plus Test (e.g. ApiExampleTest if the project is called ApiExample).
Once the project is created, right click the project to add project dependencies. The unit test project needs the project dependency to the actual project you are testing on.
(2) Create unit test
Now you can mock the DbContest interface and mock the Actorsdata. Mocking DbSet is tricky because it is not a simple list object. You needto set up all IQueryable methods. For this bit, I referenced this excellentblog post called MockEntity Framework DbSet with NSubstitute from Sina’s Blog.
Refactoring Unit Test
Now that the unit test runs, let’s refactor it a little better. First of all, we will create a class that contains mock data instead of hard coding it within the test code. In this way, we can use the same mock data for different logics.
Then, let’s take out the logic to mock Entity Framwork DbSet. For this, I am using the code example from Sina’s Blog here.
(1) CreateMockActors class
Let’s create a folder called Repositories within the test project and create a class called MockActors. When the class is instantiated, the list of actors can be accessible through the public property, Actors.
(2) Createa utility class to mock DbSet
Let’s take out the logic to create mock DbSet. This is a non-asyncversion of NSubstituteUtils from from Sina’s Blog example here.
(3) Refactorunit test to use the utility class and mock data class
Putting them all together, the test code looks much neater. I am fond of FluentAssertionsfor assertions. Check it out. It is easy to use and gives you more options than the vanilla xUnit assertion options.
Good times!
The complete Actor API code and unit test code examples can be found here.