在 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());

现在多次枚举模拟应该会按预期运行。