Every time I read about a new Entity Framework (EF) release I am hoping to find better support for mocking the physical database. I would like an in memory data provider for Entity Framework - thank you very much. It should enable seamless unit testing with a lot of benefits: fast tests, zero environment configuration, no database setup and tear down,
If you use the code first model with EF 4.1 you experience the least amount of pain - as you build your classes representing entities you can gradually build an EF abstraction that allows unit testing. An approach using the repository and unit of work patterns is covered thoroughly in the article Testability and Entity Framework 4.0 by Scott Allen. A lighter approach using a simple interface for the DbContext class is presented in this blog post How to design a unit testable domain model with Entity Framework code first by Daniel Cazzulino. Both articles give a lot of context for exploring testability with EF. I prefer the lighter approach because it has minimal code noise and it behaves like the missing interface for the DbContext class. This interface makes your EF model abstraction look like a POCO: elegant, minimalistic and unit testing friendly.
In the original Daniel's article this interface is called IDomainContext - however due to the fact that it should have been part of the EF code I will rename it to IDbContext in my sample.
I wanted to use this interface in a project that was using a database first model rather than a code first model. I found out that I could easily do this by using the DbContext generator T4 templates. These templates are created and provided by Microsoft. One template will create the DbContext derived class and the second template will create the POCO entity classes for your EF model. Looking at the first template file I could see an easy tweak that allows me to generate the required DbContext interface. Soon I had a nice looking interface that was ready for unit testing:
From now on every time I modify the .edmx file the interface class is updated automatically.
The next step is to modify the T4 template that generates the DbContext derived class to ensure it implements the IDbContext interface. Some of the methods from the IDbContext interface are implemented in a partial class for convenience, but they can be easily embedded in the T4 template.
At this point I can create unit tests against the IDbContext interface by leveraginq Moq as a convenient mocking framework.
Without the EF model abstraction a test method would look like this:
Every time I run this test the physical database is hit. For this type of test I need to maintain configuration strings, database state, database backups and restores, clean up and setup scripts. This slows me down in scenarios where I just need to test the business logic code and I don't care about database roundtrips or I don't have the development budget to maintain the database infrastructure.
But thanks to the IDbContext interface I can forget all about these issues and do this:
I am creating the test data manually and then I am injecting it into my business logic class. From now on I am freed from the concrete EF model and the physical database and I can continue writing unit tests that are cheap to run and mantain.
The code that creates the test data looks a bit clunky and repetitive: in my next blog post I will present a T4 template that creates a unit testing helper class and I will create a new version of the unit test that looks more efficient.
The full source code for this series of posts is already available on Github.
- Scott Allen has recently done a presentation where he demoes an EF interface that is similar with Daniel Cazzulino.
- Daniel Cazzulino has packaged up his interface and can be used as part of the open source NetFx NuGet library: NETFx Patterns: Domain Context for Entity Framework.