集成测试中无法在模拟InMemory数据库植入种子数据
集成测试中InMemory数据库种子数据不生效问题
问题说明
编写了包含集成测试的测试类,调用简单API接口。Setup方法中替换真实数据库为InMemory数据库并添加两个城市数据,但测试调用接口时种子数据未显示,测试失败。
测试类代码
public class TestControllerTest { private WebApplicationFactory<RentAPI.Program> _factory; private HttpClient _client; [SetUp] public void Setup() { _factory = new WebApplicationFactory<RentAPI.Program>().WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { var dbContextDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>)); services.Remove(dbContextDescriptor); services.AddDbContext<ApplicationDbContext>(options => { options.UseInMemoryDatabase(Guid.NewGuid().ToString()); }); using var scope = services.BuildServiceProvider().CreateScope(); var db = scope.ServiceProvider.GetService<ApplicationDbContext>(); SeedData(db); }); }); _client = _factory.CreateClient(); } [Test] public async Task Test_test() { var response = await _client.GetAsync("/Test"); var stingResult = await response.Content.ReadAsStringAsync(); Assert.That(stingResult, Is.EqualTo("3")); } [TearDown] public void TearDown() { _client.Dispose(); _factory.Dispose(); } public static void SeedData(ApplicationDbContext context) { context.Cities.AddRange( new City { Id = 1, Name = "City1" }, new City { Id = 2, Name = "City2" } ); context.SaveChanges(); } }
API接口代码
[ApiController, Route("[controller]")] public class TestController : ControllerBase { private readonly IUnitOfWork _uow; public TestController(IUnitOfWork uow) => _uow = uow; [HttpGet] public async Task<ActionResult<string>> Test() { await _uow.CityRepository.AddAsync(new City() { Id = 99, Name = "Poko" }); await _uow.CompleteAsync(); var cities = await _uow.CityRepository.FindAllAsync(); return cities.Count().ToString(); } }
测试失败结果
String lengths are both 1. Strings differ at index 0. Expected: "3" But was: "1" -----------^
问题原因
你在配置InMemory数据库时,将Guid.NewGuid().ToString()写在了AddDbContext的配置委托内部。这个委托会每次创建DbContext实例时执行一次,导致种子数据使用的上下文和API接口使用的上下文连接的是两个不同的InMemory数据库,因此API无法读取到种子数据,最终只统计到自己添加的1条数据。
解决方案
提前生成固定的数据库名称,确保所有DbContext实例都连接同一个InMemory数据库:
修改测试类的Setup方法:
[SetUp] public void Setup() { // 提前生成唯一数据库名 var dbName = Guid.NewGuid().ToString(); _factory = new WebApplicationFactory<RentAPI.Program>().WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { var dbContextDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>)); services.Remove(dbContextDescriptor); // 使用提前生成的固定数据库名 services.AddDbContext<ApplicationDbContext>(options => { options.UseInMemoryDatabase(dbName); }); using var scope = services.BuildServiceProvider().CreateScope(); var db = scope.ServiceProvider.GetService<ApplicationDbContext>(); SeedData(db); }); }); _client = _factory.CreateClient(); }
修改后,种子数据的上下文和API使用的上下文会连接同一个InMemory数据库,测试时接口会统计到2条种子数据+1条新增数据,返回结果为"3",测试通过。
内容的提问来源于stack exchange,提问作者Dmytro Kotenko
相关产品推荐
相关产品推荐

