Unit testing Entity Framework Core–Mocking DBSet Async methods

While working on a new project I decided to use Entity Framework core as the project had a very simple setup and didn’t needed to complex Database settings or queries. A perfect use case to try out EF core.

Implementation was just a breeze while making use of the Repository pattern and the Unit Of Work pattern. Although the application hasn’t have a load of business logic. still I wanted to add Unit tests to validate the implemented logic.

In previous projects we used Moq to create mocks to support the NUnit test framework. For this project I decided to have a look at the Fake It Easy framework. The website promises:

  • Easier semantics: all fake objects are just that — fakes. Usage determines whether they’re mocks or stubs.
  • Context-aware fluent interface guides the developer
  • Easy to use and compatible with both C# and VB.Net.

And I must say, I had to dive in the documentation a few times but for the rest, it was quite simple to set up the mocks and implement the Unit tests.

Mocking DBSet

With the experience of previous projects I knew that mocking a DBSet needed some extra setup. As long as you don’t have to mock queries on the DBSet you’re fine with the default implementation but not if you want to test async queries asFirstOrDefaultAsync(), SingleOrDefaultAsync(). Those are only supported when running against an EF query. For EF 6 there is a very well worked out example (Testing with a mocking framework) on Microsoft Docs.

For EF core there isn’t the same documentation available on the docs pages. Instead there is a page about Testing with InMemory. As already stated by Thomas Galliker in the comments (https://github.com/aspnet/EntityFramework.Docs/issues/1304) In Memory testing doesn’t cover the whole test process.

My first attempt was to use the demo code available for EF core to create the mock and try out if it would work for EF core. But instead of implementing Moq, I’ve used Fake It Easy. First you have to create a TestDbAsyncQueryProvider. I’ve copied the code from the demo on the docs page and noticed the IDbAsyncQueryProvider doesn’t exist any more. After some searching I found that it was renamed to IAsyncQueryProvider. I had to update a few implementations but got it building. The full implementation of the class:

But you also have to make some changes to setup of your mock of the DBSet:

If you now run your tests you will see they run successfully. If you are getting an error like below, make sure your set the mock of DBSet to implement IAsyncEnumerable<TEntity>

The source IQueryable doesn't implement IAsyncEnumerable{0}. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.

Generic solution

Off course you don’t want to repeat all this setup every time you have to write tests for a repository. The solution is to create a helper class where you can define the Entity (and the context if you like) like I did in the class below:

Create Nuget package to reuse in other projects

As we are going to use EF Core in future projects, it would be a timesaver to add the generic implementation in a nuget package to reuse in the Unit tests. As I was looking into creating a package to publish on Nuget I found already a generic solution created by Roman Titov called MockQueryable that was published on Nuget.

Roman already added implementations for Moq and NSubstitute but didn’t had an implementation yet for Fake It Easy. I could off course just used his core package and create my own but instead I cloned his repo and added the implementation for Fake It Easy.

So know you can just use: (https://www.nuget.org/packages/MockQueryable.FakeItEasy/)

Install-Package MockQueryable.FakeItEasy -Version 1.1.0

and get started right away on your Unit tests.

All source code from this post can  be find on Github: https://github.com/BartDM/EFCoreUnitTestingDemo

Leave a Reply

Your email address will not be published. Required fields are marked *