简体   繁体   English

模拟EF 6中的DBContext无法按预期工作

[英]Mocking DBContext in EF 6 not working as expected

I'm writing a unit test that mocks out the IDbSet properties of the DbContext; 我正在编写一个单元测试来IDbSet属性; however, I seem to be getting some strange results. 但是,我似乎得到了一些奇怪的结果。

Here's the code where I mock out the data: 这是我模拟数据的代码:

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

When I come to interrogate the data; 当我来询问数据时; for example: 例如:

using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
    var myData = myDbContext.MyData1.ToList();
}

_dbContextGenerator is simply substituted to return my test DbContext, instead of the real one: 只需替换_dbContextGenerator来返回我的测试DbContext,而不是真正的:

IDbContextGenerator dbContextGenerator = Substitute.For<IDbContextGenerator>();
dbContextGenerator.GenerateDbContext().Returns(myDbContext);            

This seems to work; 这似乎有效; however, if I call the method twice; 但是,如果我把方法调用两次; it doesn't. 它没有。 So: 所以:

using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
    myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());

Works; 作品; however: 然而:

using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
    myData = myDbContext.MyData1.ToList();
}
using (IMyDbContext myDbContext = _dbContextGenerator.GenerateDbContext())
{
    myData = myDbContext.MyData1.ToList();
}
Assert.Equal(3, myData.Count());

Does not. 才不是。 I get no data returned; 我没有得到任何数据; however, if I debug the line, I can see that: 但是,如果我调试该行,我可以看到:

myDbContextMyData1.Provider

Contains the correct test data. 包含正确的测试数据。

Please could someone point me in the right direction on this? 请有人指出我正确的方向吗?

The problem is 问题是

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

Which will return the same enumerator instance every time it is called. 每次调用它时都会返回相同的枚举器实例。

And since the enumerator is forward only, it will need to be reset. 由于枚举器只是前进,因此需要重置。 Calling it more than once without resetting will exhibit the described behavior of only being able to enumerate once because the pointer is at the end. 在没有重置的情况下多次调用它将显示所描述的行为,因为指针位于末尾,因此只能枚举一次。

Use a delegate call back so that it is invoked every time the mock is called to return a new enumerator every time GetEnumerator() is called. 使用委托回调,以便每次调用mock时调用它以在每次调用GetEnumerator()时返回新的枚举器。

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

Now enumerating the mock multiple times should then behave as expected. 现在,多次枚举模拟应该按预期运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM