所以我使用实体框架并尝试重构我的代码以使用依赖注入。在我到达DbContext之前,一切都很顺利。这是一个Windows窗体应用程序。到目前为止,我有这个:
public interface ICruiserContext
{
DbSet<Customer> Customers { get; set; }
DbSet<Address> Addresses { get; set; }
DbSet<Order> Orders { get; set; }
DbSet<Item> Items { get; set; }
DbSet<SkuMap> SkuMaps { get; set; }
DbSet<UnitOfMeasure> UnitOfMeasures { get; set; }
DbSet<RelativeUnit> RelativeUnits { get; set; }
DbSet<ShippingMethod> ShippingMethods { get; set; }
DbSet<ShippingMethodMap> ShippingMethodMaps { get; set; }
}
我有一个需要Context的控制器(大多数代码被删除):
class ShippingMethodMapper : IMapper
{
private readonly string _shippingMethod;
private readonly ICruiserContext _context;
public ShippingMethodMapper(string shippingMethod, ICruiserContext context)
{
_shippingMethod = shippingMethod;
_context = context;
}
public ICollection<string> GetRemoteValues()
{
return new List<string>
{
_shippingMethod
};
}
public ICollection<string> GetLocalValues()
{
throw new NotImplementedException();
}
public void Save(string remoteValue, string localValue)
{
throw new NotImplementedException();
}
}
因此,由于您只想对一个事务使用上下文,因此每次创建此控制器时,都需要创建一个新的上下文,但如果我只是使用
注入context = new CruiserContext();
然后创建控制器的代码不再可测试,因为它现在具有对数据库上下文的硬依赖性,并且如果上下文发生了变化,我将不得不编辑创建新实例的每个文件,违反Open /封闭原则。所以我的想法可能是使用一个简单的工厂,并委托它的实例化责任:
public static class ContextService
{
public static ICruiserContext GetContext()
{
return new CruiserContext();
}
}
但是由于静态类不能有接口,现在我只对工厂有了很强的依赖性。那么注入可以测试和模拟的dbContext的最佳方法是什么。
答案 0 :(得分:3)
使用带接口
的非静态类public interface ICruiserContextFactory
{
ICruiserContext CreateContext();
}
当您使用IDisposable实例时,这是一个标准的方法 将工厂接口传递给您的类也可以编写单元测试。
答案 1 :(得分:2)
您正确使用控制反转原理。 Nex步骤 - 使用IoC-Containers。它强大的模式将帮助您解决注射和测试中的问题。