Question

When reading/writing to a context from Entity Framework I often read, that it is recommended to keep the context's lifecycle as short as possible (one context per unit of work). It makes a lot of sense to do that, however how am I supposed to write a unit test for a class that is creating and disposing this context in every method?

Let's see a simplified fictional example code snippet:

public class Resource : IResource {
    public Item GetItem(string name) {
        using(var context = new DbContext()) {
            return context.Items.FirstOrDefault(item => item.Name == name);
        }
    }
}

If I want to unit-test the Resource, I would like to mock the DbContext, so it returns some fake data for me.

My usual approach would be to make the DbContext a property of my class and inject it from outside like this:

public class Resource : IResource {
    public DbContext Context { private get; set; }

    public Item GetItem(string name) {
        return this.Context.Items.FirstOrDefault(item => item.Name == name);
    }
}

This way, the instanciating class which injects the context is responsible for the life-cycle and I can omit the using and I can inject a mocked context of course.

Now taking into consideration, that providing a long living context might be a bad idea and following the one context per unit of work principle, this option is not favourable.

So what options do I have? One idea is to inject a ContextFactory, which creates and disposes the context on demand like this:

public class Resource : IResource {
    public DbContextFactory ContextFactory { private get; set; }

    public Item GetItem(string name) {
        using(var context = ContextFactory.CreateContext()) {
            return context.Items.FirstOrDefault(item => item.Name == name);
        }
    }
}

Does this make sense or am I going into a completely wrong directon?

Was it helpful?

Solution

The option is to use Method Injection:

   public Item GetItem(string name, DbContext context) {
        using(var context) {
            return context.Items.FirstOrDefault(item => item.Id == id);
        }
    }

Also Seemann in his book Dependency Injection in .Net uses this method to inject dependency which can change from call to call.

But I'd use ContextFactory.

OTHER TIPS

I checked out Mark Seemann's book (mentioned by Anton Sizikov) and he actually uses a factory as well, calling it an ephemeral disposable. It is somehow a Leaky Abstraction, because the factory manages the disposable dependency's life time instead of the DI container. Still it's better than having a memory leak due to undisposed disposables or exceptions caused by disposed shared dependencies.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top