在EF 6中模拟DBContext无法正常工作

时间:2018-07-17 14:46:21

标签: c# entity-framework nsubstitute

我正在编写一个模拟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仅被替换为返回测试DbContext,而不是真正的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());

不是。我没有返回任何数据;但是,如果我调试该行,则可以看到:

myDbContextMyData1.Provider

包含正确的测试数据。

请有人为此指出正确的方向吗?

1 个答案:

答案 0 :(得分:1)

问题是

myDbSet.GetEnumerator().Returns(myData1.GetEnumerator());

每次调用时都会返回相同的枚举器实例。

并且由于枚举数仅是正向的,因此需要将其重置。多次调用而不重置将表现出所描述的行为,因为指针位于末尾,因此只能枚举一次。

使用委托回调,以便在每次调用模拟程序时都调用它,以在每次调用GetEnumerator()时返回一个新的枚举数。

myDbSet.GetEnumerator().Returns(_ => myData1.GetEnumerator());

现在多次枚举模拟对象应表现出预期的效果。