如何使用 Entity Framework Core 和 Linq 测试查询?

How to test queries with Entity Framework Core and Linq?

我的 .NET Core 解决方案结构清晰。在持久性项目中,我有我的存储库。在实现中,我使用 Linq 对数据库进行了一些调用。

public class QualitativeResearchRepository 
       : BaseRepository<QualitativeResearch>, IQualitativeResearchRepository
{
    public QualitativeResearchRepository(PSCContext db,
           ILogger<QualitativeResearchRepository> log) 
           : base(db, log)
    {
    }

    public decimal GetAverageForClarity(
          Expression<Func<QualitativeResearch, bool>> func)
    {
        var list = _db.QualitativeResearches.Select(r => r.Clarity)
                      .DefaultIfEmpty();

        if (list == null || list.Count() == 0)
            return 0;

        var result = list.Average();

        return result == null ? 0 : (decimal)result;
    }
}

因此,有些函数我想应用过滤器 and/or 聚合,然后进行一些计算。我想模拟上下文(在代码 PSCContext 中),以便我可以测试过滤器和聚合是否如我预期的那样正确。 Microsoft Documentation 上有示例,但仅用于添加新记录。

对于 Entity Framework Core,Microsoft 建议使用内存中提供程序进行单元测试。它在运行时同样快速,并且比试图解开 EF 的 DbContext 的内部结构要简单得多。有关为什么这不好的更多信息,see their explanation.

We use test doubles for internal testing of EF Core. However, we never try to mock DbContext or IQueryable. Doing so is difficult, cumbersome, and fragile. Don't do it.

对于初学者,您需要安装 EF Core In Memory 提供程序。

dotnet add package Microsoft.EntityFrameworkCore.InMemory

从那里,您可以使用 DbContextOptions<T> 构造函数简单地构造您的 DbContext。

using Microsoft.EntityFrameworkCore.InMemory

// Further down...

public void GivenAnyFilter_WhenNoRecordsAreFound_ThenReturnsZero()
{
    var dbContextOptions = new DbContextOptionsBuilder<PSCContext>()
        .UseInMemoryDatabase("InMemoryDatabase")
        .Options;

    var dbContext = new PSCContext(dbContextOptions);

    // Setup your test and invoke...
}