Entity Framework unit testing with Effort data loaders

Unit Testing using an in-memory Entity Framework DbContext

April 4, 2015 - 3 minute read -
code unit-testing

I’ve recently had to introduce a certain number of unit tests into an existing product that was using Entity Framework model first. Fortunately, there is a wonderful library called Effort which allows you to abstract away your entire database with an in memory version. Without Effort, I would have been unable to add the tests I needed, due to the tightly coupled nature of the product.

Effort includes a couple of data loaders, allowing you to set the state of the datastore at the start of each test run. They include a csv data loader, allowing you to load data from csv files, plus an entity data loader, allowing you to load entities from an existing datastore, but what I really wanted was a way to define objects in code.

So, I have cobbled together an extension to Effort that will do that (currently called Effort.Extra, until I think of something better). Of course it’s also available on NuGet

The main component is the ObjectData object. It allows you to ask for a table for a specific type (table name is optional. If not supplied then the name of the entity is used) into which you can add or remove objects.

Imagine you have have types called Foo and Bar (the EF setup is outside the scope of this post).

1
2
3
4
5
6
7
8
9
10
11
public class Foo
{
    public int Id { get; set; }
    public IList<Bar> Bars { get; set; }
}

public class Bar
{
    public int Id { get; set; }
    public int FooId { get; set; }
}

You want to write a unit test that will expect the datastore to contain a Foo, which in turn contains two Bars. So, you create your ObjectData and add the items to the correct tables. Remember to include Id values, even if they would be db Identity fields ordinarily.

1
2
3
4
5
// setup code
var data = new ObjectData();
data.Table<Foo>().Add(new Foo { Id = 1 });
data.Table<Bar>().Add(new Bar { Id = 1, FooId = 1 });
data.Table<Bar>().Add(new Bar { Id = 2, FooId = 1 });

When you make your call to the Effort factory methods, just pass in a new ObjectDataLoader into which you have passed your ObjectData and Bob is your mothers brother!