Using Microsoft Fakes
Discussion
It’s pretty straightforward to add Dependency Injection to your project and create an interface for the DbContext. However, after many internet searches, it doesn’t seem obvious how best to design the unit test. Since these are popular frameworks, I’m surprised that there isn’t more concrete information on this.
For my solution, I went with the Microsoft Fakes framework, that comes with Visual Studio. One of their articles suggests using stubs to substitute for your own functionality, and that you may need to use shims for Microsoft’s frameworks. I’ve mocked other APIs, and it can be tedious to create stubs for every method; the Fakes framework generates hooks for you automatically.
Design Issues
I set up the shim context, and created a shim for one of my views, however, I got an error in the code under test where it utilizes Linq. It obtained a “null” when executing get_Provider(). While internet searches didn’t turn up anything specific on this, I realized that Linq needed additional functionality beyond the shim where I had used a List<> to hold the data. The solution I discovered was to simply wrap the List<> within an EnumerableQuery<>, and Linq was able to function with my test data.
Solution
Creating a shim is well-documented, however this additional need to provide specific functionality for Linq in order to unit test within the DbContext is not.
The sample code illustrates the wrapper, as well as the structure for what is needed to shim the views for the DbContext. Additional views are handled the same way.
I expect that there’s probably a better way to handle this, however, this seems to work well, is surprisingly straightforward, and is successful at isolating the code from the database entirely. With this solution, I was able to complete the desired unit tests for the functionality I added.
MyDbEntities testDb = new ShimMyDbEntities()
{
MyDataViewsGet = () =>
{
var dbset = new ShimDbSet<MyDataView>();
dbset.Bind(new Linq.EnumerableQuery<MyDataView> (
new List<MyDataView>
{
new MyDataView() {
FieldValue = 42,
FieldName = "testing"
},
new MyDataView() {
FieldValue = 37,
FieldName = "testing again"
}));
return dbset;
}
}
Alternatives
Repository Pattern
A common pattern is to create a repository to provide an API with CRUD operations which can hide the EF database access. Some suggest that it would allow for easier unit testing in that you would not have to mock/shim DbContext and could unit test your back-end code, although you still would not be able to unit test your repository code without returning to the original problem of needing to mock DbContext.
A number of people have cited using a Repository with EF as an anti-pattern. Entity Framework is really nice to use with Linq, so I also prefer to just use EF from the back-end code, after having tried both ways. The question is, does using the repository pattern actually buy you anything for the additional layer?
See this link for a good discussion of why you might not need to use a repository with EF. He also describes an even simpler method to stub out EF for unit testing which doesn’t require a mocking framework.