我正在为一个大型项目添加依赖注入(inject)框架,以扩大单元测试的覆盖范围。 特别是,我想涵盖数据访问方法,所以我希望能够对上下文进行 Moq。
这是一个示例方法:
public int GetNumberOfLines(int groupId)
{
using (var db = new EntitiesMigrate().AutoLocal())
{
return db.MergeUserLines.ByGroup(groupId).GroupBy(x => x.Number).Count();
}
}
AutoLocal()
方法是我编写的一个扩展,它允许我们在每个环境和不同的开发机器中使用不同的连接字符串。它用于每个 new EntitiesMigrate()
(只是说,如果它可以帮助 moqqing)。
目前我们使用的是微软的测试框架(在VS/2017中),但为了更好的测试能力,不是必须继续使用它。
我的问题是:
- 在 EF6 asp.net/mvc 和 asp.net/web-api 中组合 DI 和 MOQ 的首选框架是什么?
- 如何使用那些框架转换这个方法?
最佳答案
我已经从我的数据库上下文派生了一个接口(interface),其中包含我所有实体的 IDbSet。我注入(inject)此接口(interface)并将其用于我的所有查询。缺点是,如果您更改数据库,则必须使其与实际的数据库上下文保持同步。
public class EntitiesMigrate : IEntitiesMigrate
{
public DbSet<MyEntity> MyEntities {get; set;}
// or standardise on public IDbSet<MyEntity> MyEntities {get; set;}
public DbSet<MergeUserLine> MergeUserLines { get; set; }
}
public interface IEntitiesMigrate
{
DbSet<MyEntity> MyEntities {get; set;}
// or standardise on IDbSet<MyEntity> MyEntities {get; set;}
DbSet<MergeUserLine> MergeUserLines { get; set; }
// Don't forget SaveChanges() and whatever else you need
}
// then remove this in your classes
using (var db = new EntitiesMigrate().AutoLocal())
// instead in your constructor
public class SomeClass
{
public SomeClass(IEntitiesMigrate db)
{
_db = db;
}
}
// then testing...
var db = new Mock<IEntitiesMigrate>();
var someOtherData = new Mock<DbSet<MergeUserLine>>();
// whereas IDbSet is easier to mock, DbSet will give you all the properties and methods you need.
// see https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx for setting up mock DbSets
db.Setup(d=> d.MyEntities).Returns(someData.Object);
db.Setup(d=> d.MergeUserLines).Returns(someOtherData.Object);
你的里程可能会有所不同,但这对于模拟非常有效。
编辑
我更改了 IDbSet<T>
至 DbSet<T>
关于c# - 重构C#entity framework 6项目使用依赖注入(inject)进行拖地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50130061/