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?
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With