简体   繁体   English

如何模拟实体框架核心更改跟踪

[英]How to Mock Entity Framework Core Change Tracking

I have a Mocked Context Setup like this.我有一个这样的模拟上下文设置。

// Creates a working Fake Db Set of FakeClass Type
var fakeDbSet = Mockings.CreateDbSetMock(fakeData);  
var fakeContext = new Mock<FakeContext>();  
fakeContext.Setup(c => c.FakeData).Returns(fakeDbSet);     

Access to the Context itself an the FakeData works as intended.访问上下文本身和 FakeData 按预期工作。 But now I'm trying to write a Unit Test for a function which accesses the ChangeTracker of fakeContext.但是现在我正在尝试为访问 fakeContext 的 ChangeTracker 的函数编写单元测试。

ctx.ChangeTracker.AutoDetectChangesEnabled = false;  

Now the test fails and an Exception is thrown, because accessing the ChangeTracker of the mocked context returns null.现在测试失败并抛出异常,因为访问模拟上下文的 ChangeTracker 返回 null。

Is there a way to mock the ChangeTracker of the Context?有没有办法模拟上下文的 ChangeTracker?

I already tried to setup the mocked Context with a mocked ChangeTracker, but I can't create a valid Instance, because it requieres the Context itself in the Constructor.我已经尝试使用模拟的 ChangeTracker 设置模拟的上下文,但是我无法创建有效的实例,因为它需要构造函数中的上下文本身。

You will need to wrap the ChangeTracker call.您需要包装 ChangeTracker 调用。 It gets ugly but a way to do this would be:它变得丑陋,但一种方法是:

  1. Modify your production code to setup the context via a factory so that you can use an interface for handling the context.修改您的生产代码以通过工厂设置上下文,以便您可以使用接口来处理上下文。
     using (var ctx = _data.Create())
  2. Extend the interface to include a toggle for the tracker.扩展界面以包含跟踪器的切换。
     void SetChangeTracking(bool enabled);
  3. Extend your FakeContext to implement new wrapper interface.扩展您的 FakeContext 以实现新的包装器接口。

Then you can call the SetChangeTracking(true);然后你可以调用SetChangeTracking(true); in your production code.在您的生产代码中。 The SetChangeTracking implementation should modify the ctx object while the test code can safely return void. SetChangeTracking 实现应该修改 ctx 对象,而测试代码可以安全地返回 void。

In some cases mocking EF DbContext can be very tricky, however in most cases you do not need to (and you should not also) mock the DbContext.在某些情况下,模拟 EF DbContext 可能非常棘手,但是在大多数情况下,您不需要(也不应该)模拟 DbContext。 You can use InMemoryDatabase option instead of mocking the DbContext.(If you need functionalities such as DbQuery or any thing related to RDBMS, this will not help you)您可以使用InMemoryDatabase选项而不是模拟 DbContext。(如果您需要诸如DbQuery或任何与 RDBMS 相关的功能,这对您没有帮助)

 var options = new DbContextOptionsBuilder<MyContext>().UseInMemoryDatabase(databaseName: "MyInMemoryDB").Options;
 var ctx = new MyContext(options);

Read more about Testing In Memory 阅读有关在内存中测试的更多信息

However if you insist on having the mocked DbContext, then take a look at this thread: https://forums.asp.net/t/2155192.aspx?Mocking+EF+Core+DBContext+with+ChangeTracker但是,如果您坚持使用模拟的 DbContext,请查看此线程: https ://forums.asp.net/t/2155192.aspx?Mocking+EF+Core+DBContext+with+ChangeTracker

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

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