Introducing Effort

So what is Effort? It stands for Entity Framework Fake ObjectContext Realization Tool. Basically this is exactly what it is meant to do. Creating automated tests for data driven applications has never been a trivial task. This is also true for Entity Framework based applications, implementing proper fake ObjectContext or DbContext class requires great effort. Oh, sure… 🙂

This library approaches this problem from a very different way, it tries to emulate the underlying resource-heavy external database with a lightweight in-process in-memory database. This makes possible to run your tests rapidly without the presence of an external database. At the end of this blog post, you will see exactly how.

Effort can be downloaded from Codeplex or installed with NuGet. It is really convenient to use, practically you don’t have to do any modification to your existing ObjectContext or DbContext classes. This is presented by the following example. Let’s assume that we have an ObjectContext class called NorthwindEntities.

using(NorthwindEntities context = new NorthwindEntities())
{
    return context.Categories.ToList();
}

This code returns all the categories stored in the database. A simple modification is enough to make Entity Framework use a fake in-memory database instead:

using(NorthwindEntities context = 
    Effort.ObjectContextFactory.CreateTransient<NorthwindEntities>())
{
    return context.Categories.ToList();
}

The term “transient” refers to the lifecycle of the underlying in-memory database. The owner ObjectContext (technically the DbConnection) will be using a completely unique database instance. If the context/connection is disposed, than the database will be disposed too. If you run this code, an empty collection will be returned. This is self-evident, since the fake database was completely empty.

You could set the initial state of the database with Entity Framework, but Effort provides data loaders to do this more easily. The following example fetches the initial data from a real database:

IDataLoader loader = new EntityDataLoader("name=NorthwindEntities");

using(NorthwindEntities context = 
    ObjectContextFactory.CreateTransient<NorthwindEntities>(loader))
{
    return context.Categories.ToList();
}

This and the first code will return exactly the same collection of entities, but there is a very big difference: you can do anything you want with this data context, the result will be the same all the time. The following example proves this:

IDataLoader loader = new EntityDataLoader("name=NorthwindEntities");

using(NorthwindEntities context = 
    ObjectContextFactory.CreateTransient<NorthwindEntities>(loader))
{
    foreach (Category cat in context.Categories)
    {
        context.Categories.DeleteObject(cat);
    }
    context.SaveChanges();
}

using(NorthwindEntities context = 
    ObjectContextFactory.CreateTransient<NorthwindEntities>(loader))
{
    return context.Categories.ToList();
}

The first part of this code deletes all the categories from the database. No matter, the second part of the code will return the exact same collection like before. If you run the code again, the first part has to delete the entities again, the object set will never be empty.

Furthermore, you can completely dismiss the need of the external database. Export your data tables into local CSV files (Effort provides a tool to do it easily) and use the CSV data loader.

IDataLoader loader = new CsvDataLoader("C:\PathOfTheCsvFiles");

using(NorthwindEntities context = 
    ObjectContextFactory.CreateTransient<NorthwindEntities>(loader))
{
    return context.Categories.ToList();
}

If you run this code, there will be zero communication with the external database, but it just behaves exactly like it had.

As you can see, Effort makes possible to create automated tests for Entity Framework applications in a very convenient and powerful way. The tests can run without the presence of any external database engine. Each test can work on a completely unique database instance, so their actions will be completely isolated, they can even run concurrently. The state of database they are working on can be easily initialized too.

Future posts will reveal the capabilities of Effort for different scenarios.

Advertisements