在 EF 6 中模拟 DBContext 未按预期工作
Mocking DBContext in EF 6 not working as expected
我正在编写一个模拟 DbContext 的 IDbSet
属性的单元测试;但是,我似乎得到了一些奇怪的结果。
这是我模拟数据的代码:
var myData1 = new List<MyData1>()
{
new MyData1() { Id = 2, Test = "test" },
new MyData1() { Id = 3, Test = "test" },
new MyData1() { Id = 4, Test = "test" }
}.AsQueryable();
IDbSet<MyData1> myDbSet = Substitute.For<IDbSet<MyData1>>();
myDbSet.Provider.Returns(myData1.Provider);
myDbSet.Expression.Returns(myData1.Expression);
myDbSet.ElementType.Returns(myData1.ElementType);
myDbSet.GetEnumerator().Returns(myData1.GetEnumerator());
myDbContext.MyData1.Returns(myDbSet);
. . .
myDbContext.MyData2.Returns(myDbSet2);
. . .
myDbContext.MyData3.Returns(myDbSet3);
当我来查资料的时候;例如:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
var myData = myDbContext.MyData1.ToList();
}
_dbContextGenerator
只是替换为 return 我的测试 DbContext,而不是真实的:
IDbContextGenerator dbContextGenerator = Substitute.For<IDbContextGenerator>();
dbContextGenerator.GenerateDbContext().Returns(myDbContext);
这似乎可行;但是,如果我两次调用该方法;它没有。所以:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());
有效;然而:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());
不会。我没有得到任何数据 returned;但是,如果我调试该行,我可以看到:
myDbContextMyData1.Provider
包含正确的测试数据。
有人能为我指出正确的方向吗?
问题是
myDbSet.GetEnumerator().Returns(myData1.GetEnumerator());
每次调用时都会 return 相同的枚举器实例。
并且由于枚举器仅向前,因此需要重新设置。在不重置的情况下多次调用它会出现所描述的只能枚举一次的行为,因为指针在末尾。
使用委托回调,以便每次调用模拟时都会调用它 return 每次调用 GetEnumerator()
时都会调用一个新的枚举器。
myDbSet.GetEnumerator().Returns(_ => myData1.GetEnumerator());
现在多次枚举模拟应该会按预期运行。
我正在编写一个模拟 DbContext 的 IDbSet
属性的单元测试;但是,我似乎得到了一些奇怪的结果。
这是我模拟数据的代码:
var myData1 = new List<MyData1>()
{
new MyData1() { Id = 2, Test = "test" },
new MyData1() { Id = 3, Test = "test" },
new MyData1() { Id = 4, Test = "test" }
}.AsQueryable();
IDbSet<MyData1> myDbSet = Substitute.For<IDbSet<MyData1>>();
myDbSet.Provider.Returns(myData1.Provider);
myDbSet.Expression.Returns(myData1.Expression);
myDbSet.ElementType.Returns(myData1.ElementType);
myDbSet.GetEnumerator().Returns(myData1.GetEnumerator());
myDbContext.MyData1.Returns(myDbSet);
. . .
myDbContext.MyData2.Returns(myDbSet2);
. . .
myDbContext.MyData3.Returns(myDbSet3);
当我来查资料的时候;例如:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
var myData = myDbContext.MyData1.ToList();
}
_dbContextGenerator
只是替换为 return 我的测试 DbContext,而不是真实的:
IDbContextGenerator dbContextGenerator = Substitute.For<IDbContextGenerator>();
dbContextGenerator.GenerateDbContext().Returns(myDbContext);
这似乎可行;但是,如果我两次调用该方法;它没有。所以:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());
有效;然而:
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());
不会。我没有得到任何数据 returned;但是,如果我调试该行,我可以看到:
myDbContextMyData1.Provider
包含正确的测试数据。
有人能为我指出正确的方向吗?
问题是
myDbSet.GetEnumerator().Returns(myData1.GetEnumerator());
每次调用时都会 return 相同的枚举器实例。
并且由于枚举器仅向前,因此需要重新设置。在不重置的情况下多次调用它会出现所描述的只能枚举一次的行为,因为指针在末尾。
使用委托回调,以便每次调用模拟时都会调用它 return 每次调用 GetEnumerator()
时都会调用一个新的枚举器。
myDbSet.GetEnumerator().Returns(_ => myData1.GetEnumerator());
现在多次枚举模拟应该会按预期运行。