Тестирование интеграции ASP.NET Core 2.2 DbContext не зарегистрировано - PullRequest
2 голосов
/ 23 апреля 2019

Настройка

  • Windows 10
  • Visual Studio Professional 2017 v15.9.9
  • ASP.NET Core 2.2
  • EF Core 2.2
  • Щеголеватый
  • xUnit 2.4.1

Описание

Я использую WebApplicationFactory из пакета Microsoft.AspNetCore.Mvc.Testing для настройки интеграционных тестов.

Я следовал официальной документации , чтобы настроить конфигурацию веб-хоста.

SUT использует Dapper для запроса из базы данных, поэтому я не использую провайдера In-Memory, который поставляется с 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);
    }
}

1 Ответ

2 голосов
/ 23 апреля 2019

Во-первых, ConfigureServices может использоваться вместо UseStartup, но не вместе.Во-вторых, вам не следует создавать область действия и выполнять миграцию во время ConfigureServices в любом случае, а после создания веб-хоста см. здесь :

В более старых руководствахВы можете увидеть подобный код в методе Configure в Startup.cs.Мы рекомендуем использовать метод Configure только для настройки конвейера запросов.Код запуска приложения принадлежит методу Main.

Единственный способ сделать это не на заводе, а после того, как он был построен на заводе:

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();
        }
    }

    //...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...