0

我有一个使用IClassFixture通用工厂类的测试项目。例如

public class WeatherForecastAcceptanceTest
    : IClassFixture<WebApi1ApplicationFactory<Startup>>, IDisposable
{
    .....
}

Startup类执行ConfigureServicesConfigure方法之后,它执行 ConfigureWebHost,我在其中删除原始 DbContext 并添加一个在内存中运行的新 DbContext。

public class WebApi1ApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            //remove the injected DbContext and inject in-memory
            services.RemoveAll(typeof(DbContext));
            var connection = new SqliteConnection("Data Source=:memory:");
            services.AddDbContext<WebApi1DbContext>(
                options => options.UseSqlite(connection));

            var sp = services.BuildServiceProvider();
            using (var scope = sp.CreateScope())
            {
                //ERROR HERE WITH THE RESOLVED DbContext
                using (var dbContext = scope.ServiceProvider
                    .GetRequiredService<WebApi1DbContext>())
                {
                    try
                    {
                        dbContext.Database.OpenConnection();
                        dbContext.Database.EnsureCreated();
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }
            }
        });
    }
}

我正在解析的 DbContext 具有原始的 connectionString 而不是 InMemory,因此,我所有的测试都在我的原始数据库中插入内容。

这是我如何使用我的WebApplicationFactory

public class WeatherForecastAcceptanceTest : IClassFixture<WebApi1ApplicationFactory<Startup>>, IDisposable
    {
        private WebApi1ApplicationFactory<Startup> _factory;
        private HttpClient _client;

        public WeatherForecastAcceptanceTest(WebApi1ApplicationFactory<Startup> factory)
        {
            _factory = factory;
            _client = factory.CreateClient();
        }

        [Fact]
        public async Task GetAll_ReturnsElements_WhenPostWasExecutedSucessfully()
        {
            // Arrange
        var weatherForecastForCreationDto = CreateRandomWeatherForecastForCreationDto();

        var content = new JsonContent(weatherForecastForCreationDto);
        //setting the content-type header
        content.Headers.ContentType = new MediaTypeWithQualityHeaderValue(HttpMediaTypes.WeatherForecastType1);

        //create an object
        using (var client = _factory.CreateClient())
        {
            //act
            var responsePost = await _client.PostAsync(ApiRoutes.WeatherForecast.CreateWeatherForecast, content);
            //assert
            responsePost.StatusCode.Should().Be(StatusCodes.Status201Created);
        }

        //check that the object was inserted
        using (var client = _factory.CreateClient())
        {
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(HttpMediaTypes.WeatherForecastType1));
            // Act
            var response = await _client.GetAsync(ApiRoutes.WeatherForecast.GetWeatherForecast);

            // Assert
            response.StatusCode.Should().Be(StatusCodes.Status200OK);
            var returnedGet = await response.Content.ReadAsAsync<WeatherForecastDto[]>();
            returnedGet.Should().Contain(dto => dto.Summary == weatherForecastForCreationDto.Summary);
        }
        }

        public void Dispose()
        {
            _client?.Dispose();
            _factory?.Dispose();
        }
    }

如何解决注入的内存中 DbContext?

4

1 回答 1

0

在处理了这个问题一段时间后,根据文档,这就是他们的建议

  1. 在您的启动时读取一个测试环境变量,就像您在生产或开发中所做的那样,并为此注入正确的 DbContext。

例如用 Sqlite 注入一个内存 DBContext。

    if (_env.IsEnvironment("Test"))
    {
         var connection = new SqliteConnection(connectionDb);
         services.AddDbContextPool<WebApi1DbContext>(options => options.UseSqlite(connection));
    }
  1. 与其尝试以这种方式删除 DbContext,不如尝试将环境变量设置为 WebApplicationFactory,因为 AddDbContext 设置了 RemoveAll 未考虑的容器上的更多依赖项。
public class WebApi1ApplicationFactory<TStartup>
        : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.UseEnvironment("Test");

            builder.ConfigureServices(services =>
            {
                //DbContext in-memory is injected taking in consideration the Test environment.
                var sp = services.BuildServiceProvider();

                using (var scope = sp.CreateScope())
                {
                    using (var dbContext = scope.ServiceProvider.GetRequiredService<WebApi1DbContext>())
                    {
                        try
                        {
                            dbContext.Database.OpenConnection();
                            dbContext.Database.EnsureCreated();
                        }
                        catch (Exception ex)
                        {
                            //Log errors or do anything you think it's needed
                            throw;
                        }
                    }
                }
            });
        }
    }

此操作将允许您使用 DbContext 检索测试环境所需的 DbContext。

于 2020-07-20T17:35:20.350 回答