Unit Testing ASP.NET Web API by Mocking DbContext with NSubstitute

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.

Front-End
TypeScript: type aliases to check type equality

This post is to analyse how the type equality check by using type aliases proposed by Matt Pocock in his twitter post. These type aliases allow us to elegantly express type equality checks in unit tests. All we need to do is to pass the output and expected types in …

Front-End
Fixing it.only type error in Jest

If you are getting a type error with it.only in Jest, it could be due to incorrect TypeScript typings or incompatible versions of Jest and TypeScript. To resolve this issue, you can try the following steps: Make sure you have the latest versions of Jest and its TypeScript typings installed …

Front-End
yup conditional validation example

Here’s an example of a Yup validation logic where the first input field is optional but, if filled, it must contain only alphabetic characters, and the second input field is required: import * as Yup from “yup”; const validationSchema = Yup.object().shape({ firstField: Yup.string().matches(/^[A-Za-z]*$/, { message: “First field must contain only …