Xunit 内存数据库中的新 DBContext 类具有实时数据

Posted

技术标签:

【中文标题】Xunit 内存数据库中的新 DBContext 类具有实时数据【英文标题】:Xunit new in memory database DBContext Class has live data 【发布时间】:2021-03-07 15:18:27 【问题描述】:

我正在尝试使用 EF Core 内存数据库进行单元测试,如下所示:

namespace ContosoTests

    public class TrendServiceTests
    
       private static Microsoft.EntityFrameworkCore.DbContextOptions<TestContext> options = new 
       Microsoft.EntityFrameworkCore.DbContextOptionsBuilder<TestContext>()
                       .UseInMemoryDatabase(Guid.NewGuid().ToString())
                       .Options;

       private static TestContext _context = new TestContext(options);

       private readonly TrendService trendService = new TrendService(_context);

        private void SeedInMemoryDb()
        
            if (!_context.TrendHistories.Any())
            
                _context.TrendHistories.Add(new TrendHistory  IsActive = true, Quarter = E_Quarter.Q1, 
                TrendYear = 2020 );
            

            if (!_context.Controls.Any())
            
                _context.Controls.Add(new Control  IsActive = true);
                _context.Controls.Add(new Control  IsActive = true);
                _context.Controls.Add(new Control  IsActive = false);
            

            _context.SaveChanges();
        

我的 TestContext 继承自我的实时上下文类以避免错误:数据库提供程序“Microsoft.EntityFrameworkCore.InMemory”、“Microsoft.EntityFrameworkCore.SqlServer”的服务已在服务提供程序中注册。一个服务提供者只能注册一个数据库提供者

所以我的 TestContext 看起来像:

public class TestContext : ContosoContext
    
        public TestContext(DbContextOptions<TestContext> options)
        
            
        

        public TestContext()
        

        
    

当我在测试类中使用新的 TestContext (_context) 实例时,ContosoContext 的所有实时数据都在那里。 我期待它是没有数据的上下文类的新实例,以便我可以使用受控数据测试我的 DAL 代码。但这种情况并非如此。 我对单元测试还很陌生,因此非常感谢任何帮助。

编辑: 这是我的 contoso 上下文类的相关部分

    public class ContosoContext: IdentityDbContext<ContosoApplicationUser>
    
        public ContosoContext(DbContextOptions<ContosoContext> options) : base 
        (options)
        

        

        public ContosoContext()
        

        

        //all my DBSets here

        protected override void OnConfiguring(DbContextOptionsBuilder 
        optionsBuilder)
        

            optionsBuilder.UseSqlServer("MyConnectionString");

        
    

所以问题是我的onconfiguring方法直接处理连接字符串??

【问题讨论】:

您的ContosoContext 似乎对ServiceProvider 做了一些奇怪的事情。 ContosoContext 应该完全依赖注入的DbContextOptions 来配置连接。因此,如果不显式注入包含“实时”连接字符串的配置,它应该无法连接到该数据库。如果您将ContosoContext 的内容(或至少相关部分)复制到问题中,可能会有所帮助。 :) 另外,一般来说你不需要TestContext。如果我正确理解被测系统是ContosoContext,您应该直接使用它来使测试代表您的实时系统(相对于给定组件)。另外,TestContext 中的构造函数目前没有对 db 配置做任何事情。但如果我们看到您的ContosoContext,可能一切都会清楚。 (这很可能足以发布有用的答案。) 哦,我现在看到 TrendService 是 SUT。显然,我是个盲人。但是要对其进行单元测试,您需要将其与其他组件隔离开来,这意味着您将模拟ContosoContext。测试多个组件更像是集成测试(这也很好,实际上会给你更高的信心)。无论如何,请出示您的ContosoContext,我们可以从那里继续。 :P 【参考方案1】:

要修复错误,您需要在OnConfiguring 方法中删除optionsBuilder.UseSqlServer("MyConnectionString"); 或避免注册多个数据库提供程序,将其更改为:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

    if(!optionsBuilder.IsConfigured)
        optionsBuilder.UseSqlServer("MyConnectionString");

【讨论】:

你说得对,这解决了我的问题,现在我可以取消我正在使用的 TestContext 类 是的,你不需要额外的TestContext

以上是关于Xunit 内存数据库中的新 DBContext 类具有实时数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在需要 UserManager 但使用内存数据库的 XUnit 中测试方法

如何根据 XUnit 测试隔离 EF InMemory 数据库

Entity Framework 4.1 DbContext API 中的接口和存储库抽象中断子查询?

Xunit项目中的依赖注入

EF7DbContext池

单元测试 DbContext