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

NSubstitute单元测试失败:未检测到AppContext预期调用

问题分析与修复方案

核心问题1:断言方法与实际调用不匹配

你的MyService.AddProduct内部调用的是异步方法AddAsync和SaveChangesAsync,但测试代码里验证的是同步方法Add和SaveChanges,这直接导致断言失败——实际根本没调用同步方法。

核心问题2:可能存在DbSet模拟缺失(若服务操作的是DbSet而非直接调用DbContext方法)

如果AddProduct实际是操作AppContext中的DbSet<Product>(比如await _appContext.Products.AddAsync(mappedEntity)),而非直接调用_appContext.AddAsync,仅模拟IAppContext是不够的,还需模拟对应的Products DbSet,否则服务调用时会因DbSet为null无法触发预期方法调用。


修复步骤

步骤1:修正断言,匹配异步调用

把测试中的断言改为验证实际调用的异步方法:

// Assert
await appContext.Received(1).AddAsync(Arg.Any<Product>());
await appContext.Received(1).SaveChangesAsync();

步骤2:确保IAppContext接口包含所需异步方法

如果IAppContext是自定义接口,必须确保它包含AddAsync和SaveChangesAsync的定义,否则NSubstitute模拟的接口不会有这些方法,服务实际调用的是基类DbContext的方法,而非接口方法,导致断言失效:

public interface IAppContext : IDisposable
{
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
    Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = default) where TEntity : class;
    // 若操作DbSet,需定义对应属性
    DbSet<Product> Products { get; set; }
}

步骤3:若服务操作DbSet,需模拟DbSet并注入上下文

如果AddProduct代码是操作DbSet<Product>,比如:

public async Task AddProduct(ProductDTO dto)
{
    var product = MapToEntity(dto);
    await _appContext.Products.AddAsync(product);
    await _appContext.SaveChangesAsync();
}

则需先模拟DbSet<Product>,再赋值给IAppContext的Products属性:

// Arrange
var mockProductsDbSet = Substitute.For<DbSet<Product>, IQueryable<Product>>();
var appContext = Substitute.For<IAppContext>();
appContext.Products.Returns(mockProductsDbSet);
var myService = new MyService(appContext);

// ... 其他初始化代码

// Act
await myService.AddProduct(productDTO);

// Assert
await mockProductsDbSet.Received(1).AddAsync(Arg.Any<Product>());
await appContext.Received(1).SaveChangesAsync();

步骤4:验证实体映射(可选排查点)

若上述修复后仍失败,检查ProductDTO到Product的映射是否正确,确保映射后的实体有效,没有因映射问题导致服务内部跳过AddAsync调用。


内容的提问来源于stack exchange,提问作者hillcountry99

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:22:39