C
C#6h ago
surwren

Seeding DB for Integration Test

I am currently using TestContainers and WebApplicationFactory and am able to successfully setup a basic test which returns successfully. I am following the InProcess Example I am thinking of improving the way I populate data. Currently I populate in Program.cs
using (var scope = app.Services.CreateScope()) {
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
dbContext.Database.Migrate();
var seeder = scope.ServiceProvider.GetRequiredService<DatabaseSeeder>();
seeder.SeedAsync().Wait();
}

app.Run();

public partial class Program { }
using (var scope = app.Services.CreateScope()) {
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
dbContext.Database.Migrate();
var seeder = scope.ServiceProvider.GetRequiredService<DatabaseSeeder>();
seeder.SeedAsync().Wait();
}

app.Run();

public partial class Program { }
public class DatabaseSeeder {
private readonly AppDbContext _context;
//... services
public DatabaseSeeder(AppDbContext context, IUserService userService, ...) {
//constructor assignment for services
}
public async Task SeedAsync()
{
if (!_context.Users.Any())
{
//seeding logic
}
}
}
public class DatabaseSeeder {
private readonly AppDbContext _context;
//... services
public DatabaseSeeder(AppDbContext context, IUserService userService, ...) {
//constructor assignment for services
}
public async Task SeedAsync()
{
if (!_context.Users.Any())
{
//seeding logic
}
}
}
1 Reply
surwren
surwrenOP6h ago
From what I understand I can change my ControllerTests to something like this:
public class ControllerTests : IAsyncLifetime {
private readonly MsSqlContainer _msSqlContainer = new MsSqlBuilder().Build();
private readonly IServiceProvider _serviceProvider;

public ControllerTests() {
var services = new ServiceCollection();
services.AddSingleton(_msSqlContainer);
services.AddScoped<DatabaseSeeder>();
_serviceProvider = services.BuildServiceProvider();
}

public async Task InitializeAsync() {
await _msSqlContainer.StartAsync();

using (var scope = _serviceProvider.CreateScope()) {
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
dbContext.Database.Migrate();
var seeder = scope.ServiceProvider.GetRequiredService<DatabaseSeeder>();
await seeder.SeedAsync();
}
}
...
public class ControllerTests : IAsyncLifetime {
private readonly MsSqlContainer _msSqlContainer = new MsSqlBuilder().Build();
private readonly IServiceProvider _serviceProvider;

public ControllerTests() {
var services = new ServiceCollection();
services.AddSingleton(_msSqlContainer);
services.AddScoped<DatabaseSeeder>();
_serviceProvider = services.BuildServiceProvider();
}

public async Task InitializeAsync() {
await _msSqlContainer.StartAsync();

using (var scope = _serviceProvider.CreateScope()) {
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
dbContext.Database.Migrate();
var seeder = scope.ServiceProvider.GetRequiredService<DatabaseSeeder>();
await seeder.SeedAsync();
}
}
...
But is this the best way to do it? Do I need to inject a different service in just to seed? What are the common modern ways used for Integration tests?

Did you find this page helpful?