Unit Testing Entity Framework Queries

Introduction

When writing unit tests, we should test only one thing at once and isolate the system under test(SUT) from all the dependencies. We should follow the same approach for any LINQ queries you write to retrieve data from the underlying Database. But, I have seen many developers excluding the whole data access layer from unit testing. This is not right approach to follow IMHO. Many developers don’t bother unit testing data access layer because of the perceived effort and complexity involved in isolating the data access layer from underlying Database and ORM tools like Entity Framework. The truth is, it is very easy to test your queries without touching Entity Framework or Database.

DataContext, DbSet and Finder

Let’s assume that we have Movies database with Movie table and we want to write some queries to get top 5 movies released in year 1999. The default DbContext for this database would look like this

Unit Testing

To write unit tests for GetTopFiveMovies, we need to mock MoviesContext to provide testable implementation for Movies properties. For this example, I am going to use Moq but you can use any mocking framework you like. The completed unit test method would look like this

First, we are creating test movie data and then a mock DbSet<Movie> is created. The value of properties used by LINQ to support querying (Provider, Expression, ElementType) are replaced by the values from test data list movieList.
Then, enumerator of DbSet is assigned to the enumerator of test data list movieList. Finally, the mock DbContext returns the mock DbSet<Movie> when Movie property is accessed.

With this setup, we are providing in-memory test data to execute our query without touching EF or database.

All content on this website is licensed under the
(CC
BY-SA 3.0)
Creative Commons Attribution-ShareAlike 3.0 Unported License. All source code published here is
licensed
under the
MIT License unless explicitly stated otherwise. The
content is
provided for
educational and informational purposes only without any warranties, guarantees or conditions, of any kind,
and
may not be accurate,
up to date or complete. Any use or reliance on any content or materials published, mentioned or linked here
is
at your own risk and
the Kodebot Limited and author/authors accept no liability or responsibility for.