XUnit中InMemoryDB测试运行失败但调试通过问题求助
问题描述
生产与测试项目共用静态启动成员注入上下文,测试环境使用InMemoryDB。编写的集成测试调用仓储完成业务新增与编辑操作,调试时无断点也能通过,但运行测试时失败,报错为编辑环节找不到目标记录。已尝试异步/同步组合、Task.Wait、Task.Delay(2000),调整测试上下文生命周期(单例、瞬态、作用域),均未解决问题。
测试代码:
[Fact] public void AddEditBusiness() { var repo = app.Services.GetService<IBusinessRepo>(); var BusinessTypeRepo = app.Services.GetService<IBusinessTypesRepo>(); var ret = repo.Add(new AddBusinessRequest() { DateCreated = DateTime.Now, Name = "Test1", NationWide = true, State = true, BusinessTypes = new List<AddBusinessTypesRequest>() { new AddBusinessTypesRequest() { BusinessTypeID = 1 }, new AddBusinessTypesRequest() {BusinessTypeID = 2 } } }); Task.WaitAll(ret); var AddRes = ret.Result; var edit = repo.Edit(new EditBusinessRequest() { BusinessID = AddRes.BusinessID, Name = "EditTest1", NationWide = false, State = true, DateCreated = AddRes.DateCreated }); Task.WaitAll(edit); var editRes = edit.Result; Assert.Equal(editRes.BusinessID, AddRes.BusinessID); Assert.Equal("EditTest1", editRes.Name); Assert.Equal(false, editRes.NationWide); var btTask = BusinessTypeRepo.GetAllBursinessTypeForBusiness(new BusinessIDRequest() { BusinessID = editRes.BusinessID }); Task.WaitAll(btTask); var bt = btTask.Result; Assert.True(bt.Count == 2); }
解决方案
- 改用异步测试方法:同步阻塞(
Task.WaitAll、.Result)可能导致DbContext状态异常,改成异步测试模式:[Fact] public async Task AddEditBusiness() { using var scope = app.Services.CreateScope(); var repo = scope.ServiceProvider.GetRequiredService<IBusinessRepo>(); var BusinessTypeRepo = scope.ServiceProvider.GetRequiredService<IBusinessTypesRepo>(); var addRes = await repo.Add(new AddBusinessRequest() { DateCreated = DateTime.Now, Name = "Test1", NationWide = true, State = true, BusinessTypes = new List<AddBusinessTypesRequest>() { new() { BusinessTypeID = 1 }, new() { BusinessTypeID = 2 } } }); var editRes = await repo.Edit(new EditBusinessRequest() { BusinessID = addRes.BusinessID, Name = "EditTest1", NationWide = false, State = true, DateCreated = addRes.DateCreated }); Assert.Equal(editRes.BusinessID, addRes.BusinessID); Assert.Equal("EditTest1", editRes.Name); Assert.Equal(false, editRes.NationWide); var bt = await BusinessTypeRepo.GetAllBursinessTypeForBusiness(new BusinessIDRequest() { BusinessID = editRes.BusinessID }); Assert.True(bt.Count == 2); } - 使用作用域获取服务:通过
CreateScope()创建服务作用域,确保测试全程使用同一作用域内的DbContext实例,避免跨上下文的数据可见性问题。 - 检查仓储实现:确认
Add和Edit方法内部正确调用了SaveChangesAsync()(或同步的SaveChanges()),确保数据提交到InMemoryDB。例如:public async Task<BusinessResponse> Add(AddBusinessRequest request) { // 实体映射逻辑 _context.Businesses.Add(businessEntity); await _context.SaveChangesAsync(); // 返回响应 } - 固定InMemoryDB名称:配置测试用DbContext时指定固定数据库名称,避免每次测试创建全新内存数据库:
services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("TestBusinessDB"));
内容的提问来源于stack exchange,提问作者Trabumpaline
相关产品推荐
相关产品推荐

