Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I Moq the ApplicationDbContext in .NET Core

Tags:

I'm trying out .NET Core for the first time and seeing how Moq can be used in unit testing. Out of the box, the controllers are created where the ApplicationDbContext are parameters to the constructor like this:

public class MoviesController : Controller {     private readonly ApplicationDbContext _context;      public MoviesController(ApplicationDbContext context)     {         _context = context;         } 

Here is the unit test that I started with when testing the controller:

[TestClass] public class MvcMoviesControllerTests {     [TestMethod]     public async Task MoviesControllerIndex()     {         var mockContext = new Mock<ApplicationDbContext>();                     var controller = new MoviesController(mockContext.Object);          // Act         var result = await controller.Index();          // Assert         Assert.IsInstanceOfType(result, typeof(ViewResult));     } 

But then I realized ApplicationDbContext is a concrete class AND it does not have a parameterless constructor so the test won't work. It gives me error: Could not find parameterless constructor.

Perhaps this may be a question more aimed at Moq rather than it being related to .NET Core, but I'm also new to Moq so I'm not sure how to proceed. Here is how the ApplicationDbContext code was generated when I created the project:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> {     public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)         : base(options)     {     }      protected override void OnModelCreating(ModelBuilder builder)     {         base.OnModelCreating(builder);         // Customize the ASP.NET Identity model and override the defaults if needed.         // For example, you can rename the ASP.NET Identity table names and more.         // Add your customizations after calling base.OnModelCreating(builder);     }      public DbSet<Movie> Movie { get; set; } } 

What do I need to change so that my unit test would succeed?

UPDATE:

I discovered from https://msdn.microsoft.com/en-us/magazine/mt703433.aspx that you can configure EF Core to use an in-memory database for unit testing. So I changed my unit test to look like this:

    [TestMethod]     public async Task MoviesControllerIndex()     {                 var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();         optionsBuilder.UseInMemoryDatabase();         var _dbContext = new ApplicationDbContext(optionsBuilder.Options);          var controller = new MoviesController(_dbContext);          // Act         var result = await controller.Index();          // Assert         Assert.IsInstanceOfType(result, typeof(ViewResult));     } 

This test now succeeds. But is this the proper way of doing this? Obviously, I completely eliminated mocking the ApplicationDbContext with Moq! Or is there another solution to this problem using Moq.

like image 224
Ray Avatar asked Sep 14 '16 01:09

Ray


People also ask

Does MOQ work with .NET core?

Moq is a library that allows us to create mock objects in test code. It is also available in NuGet. This library also supports . NET Core.

What is ApplicationDbContext in asp net?

This example registers a DbContext subclass called ApplicationDbContext as a scoped service in the ASP.NET Core application service provider (a.k.a. the dependency injection container). The context is configured to use the SQL Server database provider and will read the connection string from ASP.NET Core configuration.

What is MOQ in unit testing C#?

Moq is a mocking framework for C#/. NET. It is used in unit testing to isolate your class under test from its dependencies and ensure that the proper methods on the dependent objects are being called. For more information on mocking you may want to look at the Wikipedia article on Mock Objects.

What is ApplicationDbContext C#?

The ApplicationDbContext links the database server to the data model classes in the Asp.Net application. This only calls dbContext. Table1. Field1 and has the value of a data table.


1 Answers

Mocking the DbContext doesn't work because there are too many providers that are required to make it work. A much easier solution is to use the InMemory solution that Microsoft has implemented for this exact purpose. Please don't create a repo just to test(which still doesn't test the EF code).

Here is a link to how to test with InMemory databases in .net core

https://docs.efproject.net/en/latest/miscellaneous/testing.html

like image 96
Tim Scriv Avatar answered Sep 30 '22 14:09

Tim Scriv