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

设置

  • 视窗 10

  • Visual Studio 专业版 2017 v15.9.9

  • ASP.NET 核心 2.2

  • 英孚核心 2.2

  • 小巧玲珑

  • xUnit 2.4.1

描述

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

我一直在关注官方文档来自定义虚拟主机配置。

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

我设置的代码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找不到该服务,我明白为什么(我认为)- 因为ServiceProvider我的Startup.cs班级尚未构建。


但问题是如何从我的 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);

    }

}


函数式编程
浏览 83回答 1
1回答

慕的地6264312

首先,ConfigureServices可以代替UseStartup,不能一起使用。其次,您不应该创建范围并在此期间进行迁移ConfigureServices,而是在构建 Web 主机之后,请参见此处:Configure在较早的教程中,您可能会在 Startup.cs的方法中看到类似的代码。我们建议您仅使用 Configure 方法来设置请求管道。应用程序启动代码属于该 Main方法。这样做的唯一方法不是在工厂中,而是在工厂建造之后:public class MyAPITests&nbsp; &nbsp; : IClassFixture<CustomWebApplicationFactory<Startup>>{&nbsp; &nbsp; private readonly HttpClient _client;&nbsp; &nbsp; private readonly CustomWebApplicationFactory<Startup> _factory;&nbsp; &nbsp; public MyAPITests(CustomWebApplicationFactory<Startup> factory)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _factory = factory;&nbsp; &nbsp; &nbsp; &nbsp; _client = factory.CreateClient();&nbsp; &nbsp; &nbsp; &nbsp; var host = factory.Server.Host;&nbsp; &nbsp; &nbsp; &nbsp; using (var scope = host.Services.CreateScope())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var scopedServices = scope.ServiceProvider;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var dbContext = scopedServices.GetRequiredService<MyDbContext>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dbContext.Database.EnsureCreated();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new MyDbContextSeed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .SeedAsync(dbContext)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Wait();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; //...}
打开App,查看更多内容
随时随地看视频慕课网APP