在 Entity Framework 中使用 DbSet 而不是 IDbSet 模拟数据库上下文 class
Mocking database context class with DbSet instead of IDbSet in Entity Framework
我正在开发 Asp.Net mvc 应用程序。我正在对我的应用程序进行单元测试。我使用 Moq 来模拟对象。在我的测试中,我需要模拟数据库上下文及其 DbSet。我可以模拟数据库上下文并进行测试。但问题是我必须在上下文 class.
中从 DbSet<Entity>
实体更改为 IDbSet<Entity>
实体
这是我如何模拟上下文的示例 class
[TestMethod]
public void GenerateItemCode_IncreaseDigit()
{
var data = new List<Item>{
new Item{
Id = 2,
ItemCode = "CD345678"
}
}.AsQueryable();
var dbSetMock = new Mock<IDbSet<Item>>();
dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var storeContext = new Mock<StoreContext>();
storeContext.Setup(x => x.Items).Returns(dbSetMock.Object);
ItemRepo itemRepo = new ItemRepo(storeContext.Object);
string itemCode = itemRepo.GenerateItemCode();
Assert.AreEqual(itemCode, "CD345679");
}
这是上下文class
public class StoreContext : DbContext, IDisposable
{
public StoreContext():base("DefaultConnection")
{
}
public virtual IDbSet<Item> Items { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
当我使用 IDbSet 而不是 DbSet 时,我的应用程序性能下降。因为我不能像下面那样使用
context.Items.Include("Promotions")//Cannot use Include with IDbSet
context.Items.AddRange(items)//cannot use AddRange with IDbSet
context.Items.RemoveRange(items)//cannot with IDbSet
所以我在上下文 class 中从 IDbSet 更改为 DbSet,如下所示
public virtual DbSet<Item> Items { get; set; }
然后单元测试开始抛出错误。因为上下文 class 的项目不能用我嘲笑的方式来嘲笑。下面是错误的截图。
所以我在单元测试中从 IDbSet 更改为 DbSet。然后报错就变成这样了
如何为单元测试模拟上下文 class 的 DbSet 实体?
问题更新后我可以重现你的问题。您刚刚忘记转换到正确的接口 IQueryable:
var dbSetMock = new Mock<DbSet<Item>>();
dbSetMock.As<IQueryable<Item>>().Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
如果您想知道为什么必须强制转换才能设置提供程序,因为 IQueryable 的显式接口实现。更多信息:https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx
我正在开发 Asp.Net mvc 应用程序。我正在对我的应用程序进行单元测试。我使用 Moq 来模拟对象。在我的测试中,我需要模拟数据库上下文及其 DbSet。我可以模拟数据库上下文并进行测试。但问题是我必须在上下文 class.
中从DbSet<Entity>
实体更改为 IDbSet<Entity>
实体
这是我如何模拟上下文的示例 class
[TestMethod]
public void GenerateItemCode_IncreaseDigit()
{
var data = new List<Item>{
new Item{
Id = 2,
ItemCode = "CD345678"
}
}.AsQueryable();
var dbSetMock = new Mock<IDbSet<Item>>();
dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var storeContext = new Mock<StoreContext>();
storeContext.Setup(x => x.Items).Returns(dbSetMock.Object);
ItemRepo itemRepo = new ItemRepo(storeContext.Object);
string itemCode = itemRepo.GenerateItemCode();
Assert.AreEqual(itemCode, "CD345679");
}
这是上下文class
public class StoreContext : DbContext, IDisposable
{
public StoreContext():base("DefaultConnection")
{
}
public virtual IDbSet<Item> Items { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
当我使用 IDbSet 而不是 DbSet 时,我的应用程序性能下降。因为我不能像下面那样使用
context.Items.Include("Promotions")//Cannot use Include with IDbSet
context.Items.AddRange(items)//cannot use AddRange with IDbSet
context.Items.RemoveRange(items)//cannot with IDbSet
所以我在上下文 class 中从 IDbSet 更改为 DbSet,如下所示
public virtual DbSet<Item> Items { get; set; }
然后单元测试开始抛出错误。因为上下文 class 的项目不能用我嘲笑的方式来嘲笑。下面是错误的截图。
所以我在单元测试中从 IDbSet 更改为 DbSet。然后报错就变成这样了
如何为单元测试模拟上下文 class 的 DbSet 实体?
问题更新后我可以重现你的问题。您刚刚忘记转换到正确的接口 IQueryable:
var dbSetMock = new Mock<DbSet<Item>>();
dbSetMock.As<IQueryable<Item>>().Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.As<IQueryable<Item>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
如果您想知道为什么必须强制转换才能设置提供程序,因为 IQueryable 的显式接口实现。更多信息:https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx