当从Entity Framework读取/写入上下文时,我经常看到建议尽可能缩短上下文的生命周期(每个工作单元一个上下文)。这是非常有道理的,但是如果每个方法都创建和释放此上下文,则该类如何编写单元测试?
让我们看一个简化的虚构示例代码片段:
public class Resource : IResource {
public Item GetItem(string name) {
using(var context = new DbContext()) {
return context.Items.FirstOrDefault(item => item.Name == name);
}
}
}
如果我想对资源进行单元测试,我希望能够模拟DbContext,以便为我返回一些虚假数据。
我的常规方法是将DbContext作为我的类的属性,并像这样从外部注入它:
public class Resource : IResource {
public DbContext Context { private get; set; }
public Item GetItem(string name) {
return this.Context.Items.FirstOrDefault(item => item.Name == name);
}
}
这样,注入上下文的实例化类负责生命周期,我可以省略使用,当然也可以注入模拟上下文。
现在考虑到提供长时间存活的上下文可能是一个不好的主意,并且遵循“每个工作单元一个上下文”的原则,这个选项并不理想。
那么我有什么选择?一种想法是注入一个ContextFactory,根据需要创建和处理上下文,就像这样:
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);
}
}
}
这是不是有意义,或者我走了一个完全错误的方向?
DbContext
的IRepository
应该被模拟。 - Dustin Kingen