How to Mock EF Core DbContext - Code Maze (2024)

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API programand learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

While unit-testing EF Core applications, sometimes, we may want to mock EF Core DbContext. In this article, we’ll talk about a few ways of doing that.

To download the source code for this article, you can visit our GitHub repository.

Let’s get going.

When to Mock EF Core DbContext

There are different ways in which we can test an application that uses the EF Core database. The first and foremost option is to test it against an actual production database. This ensures that the application behaves as expected in production as well. However, it is not always feasible to test an application with an actual production database. This brings us to the next option – testing our application using some fake data.

If we are planning to use fake test data, then the best option is to implement a repository pattern and mock the data access layer. By implementing this, we can have a clear separation between the data access layer and the business logic of our application. Apart from that, we can easily test our application as well using this pattern.

However, if implementing a repository pattern is not viable for an application, then we can think of either using a fake EF Core provider like SQLite, In-Memory, etc., or mocking the DbContext.

We are going to learn how to mock an EF Core DbContext by using two popular libraries:

  • Moq.EntityFrameworkCore
  • MockQueryable

Without further ado, let’s start.

Preparing the Environment

First, let’s configure an EF Core application.

As explained in the linked article, let’s create an Employee model for this example:

public class Employee{ public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Phone { get; set; }}

After creating the context file and updating the database, let’s create a controller with two action methods:

public class EmployeesController : ControllerBase{ private readonly EmployeeDBContext _context; public EmployeesController(EmployeeDBContext context) { _context = context; } // GET: api/Employees [HttpGet] public async Task<ActionResult<IEnumerable<Employee>>> GetEmployees() { return await _context.Employees.ToListAsync(); } // GET: api/Employees/5 [HttpGet("{id}")] public async Task<ActionResult<Employee>> GetEmployeeById(int id) { var employee = await _context.Employees.FindAsync(id); if (employee is null) { return NotFound(); } return employee; }}

Here we have the GetEmployees() method that returns all employee records and the GetEmployeeById() method that fetches the employee record with the specified Id.

Feel free to skip creating a repository layer in this example as our focus in this article is on mocking EF Core DbContext when implementing a repository pattern is not feasible.

How to Mock EF Core DbContext Using Moq.EntityFrameworkCore

Now, let’s take a look at how to mock EF Core DbContext using the Moq.EntityFrameworkCore library. For that, let’s install the Moq.EntityFrameworkCore NuGet package:

Install-Package Moq.EntityFrameworkCore

This library will help us to mock EF Core contexts and we can test methods that are using the DbContext, DbSet, etc.

We can reference the library by including the Moq.EntityFrameworkCore namespace:

using Moq.EntityFrameworkCore;

Now, let’s write a test for the GetEmployees() method:

[Fact]public async Task GetEmployees_WhenCalled_ReturnsEmployeeListAsync(){ // Arrange var employeeContextMock = new Mock<EmployeeDBContext>(); employeeContextMock.Setup<DbSet<Employee>>(x => x.Employees) .ReturnsDbSet(TestDataHelper.GetFakeEmployeeList()); //Act EmployeesController employeesController = new(employeeContextMock.Object); var employees = (await employeesController.GetEmployees()).Value; //Assert Assert.NotNull(employees); Assert.Equal(2, employees.Count());}

Here we mock the DbContext and set up the Employee DbSet to return a fake employee list:

private static List<Employee> GetFakeEmployeeList(){ return new List<Employee>() { new Employee { Id = 1, Name = "John Doe", Email = "[emailprotected]", Phone = "123-456-7890" }, new Employee { Id = 2, Name = "Mark Luther", Email = "[emailprotected]", Phone = "123-456-7890" } };}

Now, what about testing the GetEmployeeById() method? This method uses the DbSet.FindAsync() method for fetching an employee record and we need to mock that method. But Moq.EntityFrameworkCore doesn’t provide any inbuilt way of mocking the FindAsync() method. However, the good news is that we can still test this by mocking the DbContext and setting up the FindAsync() method:

[Fact]public async Task GetEmployeeById_WhenCalled_ReturnsEmployeeAsync(){ // Arrange var employeeContextMock = new Mock<EmployeeDBContext>(); employeeContextMock.Setup(x => x.Employees.FindAsync(1).Result) .Returns(TestDataHelper.GetFakeEmployeeList().Find(e => e.Id == 1) ?? new Employee()); //Act EmployeesController employeesController = new(employeeContextMock.Object); var employee = (await employeesController.GetEmployeeById(1)).Value; //Assert Assert.NotNull(employee); Assert.Equal(1, employee.Id);}

Here we mock the DbContext and set up the FindAsync() method of the DbSet to return a particular employee record when we pass a particular Id. Using this, we can test the GetEmployeeById() method.

How to Mock EF Core DbContext Using MockQueryable

The MockQueryable library provides extensions for mocking EF Core operations like ToListAsync(), FindAsync(), etc. It works pretty well with mocking libraries like Moq, NSubstitute, and FakeItEasy. Now let’s see how to mock EF Core DbContext using the MockQueryable library for the same example.

For using MockQueryable, first, we need to install the NuGet package corresponding to the mocking library that we use. Since we are using Moq, let’s install MockQueryable.Moq package:

Install-Package MockQueryable.Moq

Similarly, if we are using NSubstitute, we can use the MockQueryable.NSubstitute package and with FakeItEasy, we can use the MockQueryable.FakeItEasy package.

After that, we can reference the library by including the specific namespace, in our case the MockQueryable.Moq :

using MockQueryable.Moq;

Now, let’s write a test for the GetEmployees() method:

[Fact]public async Task GetEmployees_WhenCalled_ReturnsEmployeeListAsync(){ // Arrange var mock = TestDataHelper.GetFakeEmployeeList().BuildMock().BuildMockDbSet(); var employeeContextMock = new Mock<EmployeeDBContext>(); employeeContextMock.Setup(x => x.Employees).Returns(mock.Object); //Act EmployeesController employeesController = new(employeeContextMock.Object); var employees = (await employeesController.GetEmployees()).Value; //Assert Assert.NotNull(employees); Assert.Equal(2, employees.Count());}

Here, first, we build a mock DbSet using the fake employee list. After that, we set up the DbContext to return this DbSet. This way, we can test the GetEmployees() method by using a mock DbSet.

Next, we are going to test the GetEmployeeById() method. As we mentioned earlier, this method uses the DbSet.FindAsync() method for fetching a specific employee record. The good news here is that the MockQueryable library provides inbuilt support for mocking the FindAsync() method of the mock DbSet that we create. So let’s write a test by mocking the DbSet.FindAsync() method:

[Fact]public async Task GetEmployeeById_WhenCalled_ReturnsEmployeeAsync(){ // Arrange var mock = TestDataHelper.GetFakeEmployeeList().BuildMock().BuildMockDbSet(); mock.Setup(x => x.FindAsync(1)).ReturnsAsync( TestDataHelper.GetFakeEmployeeList().Find(e => e.Id == 1)); var employeeContextMock = new Mock<EmployeeDBContext>(); employeeContextMock.Setup(x => x.Employees) .Returns(mock.Object); //Act EmployeesController employeesController = new(employeeContextMock.Object); var employee = (await employeesController.GetEmployeeById(1)).Value; //Assert Assert.NotNull(employee); Assert.Equal(1, employee.Id);}

Here, we create a mock DbSet and set up the FindAsync() method. Next, we set up a mock DbContext using this DbSet. Now since we have mocked the DbSet.FindAsync() method, we can easily test the GetEmployeeById() method.

Moq.EntityFrameworkCore vs MockQueryable

We use the Moq.EntityFrameworkCore for mocking EF Core contexts. By using it, we can easily test methods that are using the DbSet or DbQuery from the DbContext. However, this library supports only the Moq library for mocking. So if we are using Moq andwe just want to mock a DbSet or DbQuery, then it makes perfect sense to use this library. On the other hand, if we want to use other mocking libraries like NSubstitute orFakeItEasy or if we want to mock EF Core query operations, then this library will not work.

MockQueryable provides extensions for mocking several EF Core operations such as FindAsync(), ToListAsync(), FirstOrDefaultAsync(), etc. It helps us in building a mock DbSet and then set up these EF Core methods inside it. This is very helpful in testing methods that implement EF Core query operations. Additionally, it supports different mocking libraries such as Moq, NSubstitute, and FakeItEasy. So if we are using any of these mocking libraries and want to test methods that implement various EF Core operations, then MockQueryable is a great choice.

Conclusion

In this article, we learned how to mock EF Core DbContext. We used two libraries Moq.EntityFrameworkCore and MockQueryable and saw how to write unit tests using those and which one to use in which scenario etc.

Want to build great APIs? Or become even better at it? Check our Ultimate ASP.NET Core Web API programand learn how to create a full production-ready ASP.NET Core API using only the latest .NET technologies. Bonus materials (Security book, Docker book, and other bonus files) are included in the Premium package!

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!

How to Mock EF Core DbContext - Code Maze (2024)
Top Articles
Latest Posts
Article information

Author: Prof. An Powlowski

Last Updated:

Views: 6012

Rating: 4.3 / 5 (64 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Prof. An Powlowski

Birthday: 1992-09-29

Address: Apt. 994 8891 Orval Hill, Brittnyburgh, AZ 41023-0398

Phone: +26417467956738

Job: District Marketing Strategist

Hobby: Embroidery, Bodybuilding, Motor sports, Amateur radio, Wood carving, Whittling, Air sports

Introduction: My name is Prof. An Powlowski, I am a charming, helpful, attractive, good, graceful, thoughtful, vast person who loves writing and wants to share my knowledge and understanding with you.