【发布时间】:2020-10-22 16:35:50
【问题描述】:
我有一个使用通用工厂类的IClassFixture 的测试项目。
例如
public class WeatherForecastAcceptanceTest
: IClassFixture<WebApi1ApplicationFactory<Startup>>, IDisposable
{
.....
}
在Startup 类执行ConfigureServices 和Configure 方法后,它会执行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?
【问题讨论】:
-
根据您发布的代码,我看不出解析
WebApi1DbContext不会获得最后注册的WebApi1DbContext的原因。这意味着发布的代码中不存在某些正在发生的事情。尝试构建MRE 并使用该代码更新问题。如果没有这些信息,恐怕您的问题会在没有得到满意答案的情况下结束。 -
我会尝试用代码发布一个github repo
-
嗨 Zinov,请不要那样做。 Stack Overflow 问题必须独立存在。这意味着 all 相关代码必须是您帖子的一部分。为确保您发布重现问题的最少量代码,请尝试创建一个演示问题的控制台应用程序。
-
@Steven,这无法在控制台应用程序上复制,您至少需要 2 个项目,一个用于您的 API,另一个用于测试。我认为上面的代码足以复制问题,知道.net核心上的TestServer和IClassFixture的人应该毫无问题地复制它。我将用更多细节更新我的问题,以提供更多背景信息。谢谢
标签: c# unit-testing dependency-injection entity-framework-core testserver