I have a test project that uses IClassFixture
of a generic factory class.
For example
public class WeatherForecastAcceptanceTest
: IClassFixture<WebApi1ApplicationFactory<Startup>>, IDisposable
{
.....
}
after the Startup
class executes ConfigureServices
and Configure
methods it executes the ConfigureWebHost where I remove the original DbContext and add a new one that runs in memory.
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;
}
}
}
});
}
}
The DbContext that I am resolving has the original connectionString instead of InMemory, as a result, all my testings are inserting content on my original database.
Here is how I am using my 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();
}
}
How can I resolve the in-memory DbContext that was injected?