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.
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.