【问题标题】:Moq and Entity Framework Core do not really work with asynchronous methods?Moq 和 Entity Framework Core 不能真正使用异步方法?
【发布时间】:2018-10-05 02:55:15
【问题描述】:

我正在尝试使用 Moq 和 EF Core 创建一个测试存储库,使用它的异步方法(如 AddAsyncSaveChangesAsync),但我没有取得丝毫成功...

我找到了很多博客文章(包括这里的问题),但对我没有任何帮助。

例如,我从字面上复制了这篇文章的代码并尝试实现它的引用:[https://fpnotebook.wordpress.com/2017/05/29/asp-net-core-testing-repositories-and-mocking-ef/] 但问题总是一样的,例如:

消息:Moq.MockException:
预期在模拟上调用一次,但为 0 次:m => m.AddAsync (It.IsAny (),)
未配置任何设置。

SaveChangesAsync 也是如此。

这是我一直在尝试实现的示例代码:

//配置

dbSetMock.Setup(m => m.AddAsync(It.IsAny<T>), It.IsAny<CancellationToken>()))
    .Callback ((T model, CancellationToken token) => {queryableList.Concat (new [] {model})}})
    .Returns ((T model, CancellationToken token) => Task.FromResult((EntityEntry<T>) null));

// 测试本身

[Fact]
public async void AddAsyncTest ()
{
    var mockSet = new Mock <DbSet <Wine >> ();

    var mockContext = new Mock <SQLContext> (_ options);
    mockContext.Setup (m => m.Set <Wine> ()). Returns (mockSet.Object);

    var service = new WineCommandRepository (mockContext.Object);
    await service.Insert (new Wine
    {
        IdWine = 1,
        Name = "Wine1"
    });
    mockContext.Object.SaveChanges ();

    mockSet.Verify (m => m.AddAsync (It.IsAny <Wine>), 
        new CancellationToken ()), Times.Once ());

    mockContext.Verify (m => m.SaveChanges (), Times.Once ());
}

我的代码没有什么特别之处,我使用了我一直用于同步存储库的东西,但这种情况对我来说是新的。

有没有人克服了这个问题并有一些例子或建议可以分享?

【问题讨论】:

  • 显示被测代码以及如何访问 DbSet
  • 避免对 DbContext/DbSet(或其他 EF 类型)使用 Mocks。它可能会导致问题而不是工作。而是使用 InMemory 提供程序或 SQLite 内存数据库进行测试。 docs.microsoft.com/en-us/ef/core/miscellaneous/testing
  • “避免对 DbContext/DbSet(或其他 EF 类型)使用 Mocks。”那你有什么建议呢?
  • 我正在使用 InMemory 进行测试

标签: c# mocking .net-core entity-framework-core moq


【解决方案1】:

我怀疑这不起作用的原因是这个检查(为此我从问题中添加了缺失的括号并删除了不必要的括号)永远不会通过:

mockSet.Verify(m => m.AddAsync(It.IsAny<Wine>()), new CancellationToken()), Times.Once);

原因是Verify 正在检查该方法是否使用提供的参数调用,而不是“等效”,而是您告诉它的内容(引用等于)。然而,Verify 被赋予了一个新的 CancellationToken 实例,并且不可能测试的代码将返回一个 CancellationToken 的确切实例。

您需要使用It.IsAny&lt;CancellationToken&gt;(),或者如果您将被测代码从显式使用new CancellationToken()抽象出来,并通过测试设置提供,那么您可以将该特定实例提供给Verify

当我在这里时,如果您不知道,我应该注意使用It.IsAny。看一下this question 的未接受答案和 cmets,然后是接受的答案。

【讨论】:

  • 不幸的是我的问题,不。我现在必须处理其他事情,但很快我会继续这项任务并报告进度。
猜你喜欢
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 2020-12-15
  • 2017-03-21
  • 2019-02-19
  • 1970-01-01
  • 2014-01-30
  • 2015-02-24
相关资源
最近更新 更多