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



我有一个这样的模拟上下文设置。

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

访问上下文本身和假数据按预期工作。 但是现在我正在尝试为访问fakeContext的ChangeTracker的函数编写一个单元测试。

ctx.ChangeTracker.AutoDetectChangesEnabled = false;  

现在测试失败并引发异常,因为访问模拟上下文的更改跟踪器将返回 null。

有没有办法模拟上下文的ChangeTracker?

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

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

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

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

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

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

阅读更多 关于 内存测试

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

最新更新