【问题标题】:Retrieving ASP.NET Core 3.1 database context in Xunit integration test在 Xunit 集成测试中检索 ASP.NET Core 3.1 数据库上下文
【发布时间】:2020-09-14 19:09:14
【问题描述】:

我一直在使用 Xunit 为使用数据库的 .NET Core 3.1 Web 应用程序创建集成测试。为了测试,我从Microsoft Documentation 切换到内存数据库。 CustomWebApplicationFactory 代码是:

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
        {
        protected override void ConfigureWebHost(IWebHostBuilder webHostBuilder)
            {
            webHostBuilder.ConfigureServices(services =>
                {
                    // Remove the app's database  registration.
                    var serviceDescriptor = services
                                                .SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<MyDbContext>));

                    if (serviceDescriptor != null)
                        {
                        services.Remove(serviceDescriptor);
                        }

                    // Add MyDbContext using an in-memory database for testing.
                    services.AddDbContext<MyDbContext>(options =>
                    {
                        options.UseInMemoryDatabase("InMemoryDbForTesting");
                    });

                    var servicesProvider = services.BuildServiceProvider();

                    // Create a scope to obtain a reference to the database context (MyDbContext).
                    using (var serviceScope = servicesProvider.CreateScope())
                        {
                        var scopedServices = serviceScope.ServiceProvider;
                        var db = scopedServices.GetRequiredService<MyDbContext>();
                        var logger = scopedServices.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                        db.Database.EnsureCreated();                                                                                                                                         // Ensure the database is created.

                        try
                            {
                            DatabaseSeeding.voidInitialiseCazIdentityProviderDatabase(db);                                                                                                                              // Seed the database with test data.
                            }
                        catch (Exception ex)
                            {
                            logger.LogError(ex, $"An error occurred seeding the database with data. Error: {ex.Message}");
                            }
                        }
                });
            }

我的基本页面测试在这种安排下运行良好,但我现在想检查内存数据库是否已被集成测试修改。无论发生什么,对数据库的引用都不会在 Xunit DI 容器中结束(如果存在这种情况)。我的测试类使用以下代码初始化:

    public class IdpUserServiceTests : IClassFixture<CustomWebApplicationFactory<Startup>>
    {
    private readonly CustomWebApplicationFactory<Startup> _webApplicationFactory;
    private readonly ITestOutputHelper _testOutput;
    private readonly HttpClient _httpClient;
    private readonly MyDbContext _myDbContext;

    public IdpUserServiceTests(CustomWebApplicationFactory<Startup> webApplicationFactory, MyDbContext myDbContext, ITestOutputHelper testOutput)
        {
        _webApplicationFactory = webApplicationFactory;
        _myDbContext = myDbContext;
        _testOutput = testOutput;
        _httpClient = _webApplicationFactory.CreateClient();
        }

    //Tests 

但在尝试运行测试时,我收到以下错误:

The following constructor parameters did not have matching fixture data: MyDbContext objMyDbContext

我正在寻找访问内存数据库的正确方法——显然不是通过构造函数注入。我已经接受了这个答案 - Access in memory dbcontext in integration test - 但事情似乎在 2.2 和 3.1 之间发生了变化。

【问题讨论】:

    标签: c# integration-testing xunit asp.net-core-3.1


    【解决方案1】:

    事实证明,上面引用的 Access in memory dbcontext in integration test 答案对于 ASP.NET Core 3.1 并不完全正确。 scopeFactory 必须从不同的来源找到:

    var scopeFactory = _webApplicationFactory.Services.GetService<IServiceScopeFactory>();
    

    所以测试类现在看起来像:

    public class ServiceTests : IClassFixture<CustomWebApplicationFactory<Startup>>
        {
        private readonly CustomWebApplicationFactory<Startup> _webApplicationFactory;
        private readonly ITestOutputHelper _testOutput;
        private readonly HttpClient _httpClient;
    
        public ServiceTests(CustomWebApplicationFactory<Startup> webApplicationFactory, ITestOutputHelper testOutput)
            {
            _webApplicationFactory = webApplicationFactory;
            _testOutput = testOutput;
            _httpClient = _webApplicationFactory.CreateClient();
            }
    
        [Fact]
    
        public async Task AServiceTest()
            {
            // Do some HTTP client stuff that alters the in-memory database
    
          var scopeFactory = _webApplicationFactory.Services.GetService<IServiceScopeFactory>();
    
            using(var scope = scopeFactory.CreateScope())
                {
                var myDataContext = scope.ServiceProvider.GetService<MyDataContext>();
    
                // Query the in-memory database
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2018-12-26
      • 2020-05-09
      • 2020-08-18
      • 1970-01-01
      • 2017-12-12
      • 2020-10-27
      相关资源
      最近更新 更多