c# - ASP.NET Core 2.2 集成测试 DbContext 服务未注册

标签 c# asp.net-core

设置

  • Windows 10
  • Visual Studio 专业版 2017 v15.9.9
  • ASP.NET 核心 2.2
  • EF 核心 2.2
  • 小巧玲珑
  • xUnit 2.4.1

描述

我正在使用 Microsoft.AspNetCore.Mvc.Testing 包中的 WebApplicationFactory 来设置我的集成测试。

我一直在关注 official documentation自定义 Web 主机配置。

SUT 使用 Dapper 从数据库中查询,因此我没有使用 EF Core 附带的 In-Memory 提供程序来进行此特定集成测试。

我设置 WebApplictionFactory 的代码如下:

public class CustomWebApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder
            .UseStartup<TStartup>()
            .ConfigureServices(services =>
        {
            var sp = services.BuildServiceProvider();

            // Create a scope to obtain a reference to the database context
            using (var scope = sp.CreateScope())    
            {
                var scopedServices = scope.ServiceProvider;
                var dbContext = scopedServices.GetRequiredService<MyDbContext>(); // <-- service not found

                dbContext.Database.EnsureCreated();

                new MyDbContextSeed()
                    .SeedAsync(dbContext)
                    .Wait();
            }
        });
    }
}

问题

未找到 MyDbContext 服务,我明白为什么(我认为)- 因为我的 Startup.cs 类中的 ServiceProvider 没有'尚未建成。

但问题是我如何从此处的 Startup 类访问服务?

对于上下文,集成测试如下所示:

public class MyAPITests
    : IClassFixture<CustomWebApplicationFactory<Startup>>
{
    private readonly HttpClient _client;
    private readonly CustomWebApplicationFactory<Startup> _factory;

    public MyAPITests(CustomWebApplicationFactory<Startup> factory)
    {
        _factory = factory;
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Get_ItemAsync_WhenIdNotFound_ReturnsNotFoundStatusCode()
    {
        // Arrange
        var request = new HttpRequestMessage(HttpMethod.Get, "api/v1/item/0");

        // Act
        var response = await _client.SendAsync(request);

        // Assert
        Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
    }
}

最佳答案

首先,ConfigureServices可以代替UseStartup,不能一起使用。其次,您无论如何都不应该在 ConfigureServices 期间创建作用域并进行迁移,而是在构建 Web 主机之后,参见 here :

In older tutorials, you may see similar code in the Configure method in Startup.cs. We recommend that you use the Configure method only to set up the request pipeline. Application startup code belongs in the Main method.

唯一的办法不是在工厂里,而是在工厂建成之后:

public class MyAPITests
    : IClassFixture<CustomWebApplicationFactory<Startup>>
{
    private readonly HttpClient _client;
    private readonly CustomWebApplicationFactory<Startup> _factory;

    public MyAPITests(CustomWebApplicationFactory<Startup> factory)
    {
        _factory = factory;
        _client = factory.CreateClient();

        var host = factory.Server.Host;
        using (var scope = host.Services.CreateScope())
        {
            var scopedServices = scope.ServiceProvider;
            var dbContext = scopedServices.GetRequiredService<MyDbContext>();

            dbContext.Database.EnsureCreated();

            new MyDbContextSeed()
                .SeedAsync(dbContext)
                .Wait();
        }
    }

    //...
}

关于c# - ASP.NET Core 2.2 集成测试 DbContext 服务未注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55812037/

相关文章:

c# - 在 .net core api 中不使用模型验证查询参数

c# - 使用传统 [] 数组语法的 C# 中基于非 0 的数组?

c# - .NET Framework 类如何在不特定位数的情况下引用 native Windows DLL?

c# - 使用正则表达式 C# 获取包含特定单词的整行

c# - Web Essentials 浏览器链接在 asp mvc 6 项目中不起作用

c# - 如何使用复杂对象发出 GET 请求?

c# - 查找是否多次包含相同元素的字符串列表

c# - 为什么多维数组的枚举值不等于自身?

azure - 获取 Azure AD B2C token 时出错

http - 为什么我看不到 HttpUtility.ParseQueryString 方法?