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

时间:2019-07-01 17:25:40

标签: c# unit-testing mocking entity-framework-core moq

我有一个类似的模拟上下文设置。

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

访问Context本身,FakeData按预期工作。 但是,现在我正在尝试为访问访问fakeContext的ChangeTracker的函数编写单元测试。

ctx.ChangeTracker.AutoDetectChangesEnabled = false;  

现在测试失败,并引发异常,因为访问模拟上下文的ChangeTracker返回null。

是否可以模拟上下文的ChangeTracker?

我已经尝试使用模拟的ChangeTracker来设置模拟的Context,但是我无法创建有效的实例,因为它需要构造函数中的Context本身。

2 个答案:

答案 0 :(得分:0)

您将需要包装ChangeTracker调用。它变得丑陋,但是一种实现方法是:

  1. 修改生产代码以通过工厂设置上下文,以便您可以使用接口来处理上下文。
    using (var ctx = _data.Create())
  2. 扩展界面以包括跟踪器的切换。
    void SetChangeTracking(bool enabled);
  3. 扩展您的FakeContext以实现新的包装器接口。

然后,您可以在生产代码中调用SetChangeTracking(true);。在测试代​​码可以安全返回void的同时,SetChangeTracking实现应修改ctx对象。

答案 1 :(得分:0)

在某些情况下,对EF DbContext进行模拟可能非常棘手,但是在大多数情况下,您不需要(并且也不应)对DbContext进行模拟。您可以使用InMemoryDatabase选项而不是模拟DbContext。(如果您需要DbQuery之类的功能或与RDBMS相关的任何功能,这将不会对您有帮助)

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

Read more about Testing In Memory

但是,如果您坚持要模拟DbContext,请查看以下线程:https://forums.asp.net/t/2155192.aspx?Mocking+EF+Core+DBContext+with+ChangeTracker