You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:55:03