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

使用NSubstitute模拟Durable Task对象触发空引用异常的排查与解决

问题分析与修复方案

问题根源

  1. IDurableActivityContext未模拟输入返回值:测试中的_activityCtx没有设置GetInput<EligibleMember>()的返回结果,导致业务方法里var input = ctx.GetInput<EligibleMember>()得到null,后续访问input.AccountNumber触发空引用异常。
  2. IEnumerable模拟不当:用Substitute.For<IEnumerable<FulfillmentProcess>>()模拟的集合,调用ToList()时可能因枚举器未正确模拟引发问题,直接返回实际空集合更可靠。

修复后的测试用例

[Fact]
public async Task CanCallTriggerTableDataAsync()
{
    // 模拟IDurableActivityContext的GetInput方法,返回带AccountNumber的测试实例
    var testMember = new EligibleMember { AccountNumber = "test-account-123" };
    _activityCtx.GetInput<EligibleMember>().Returns(testMember);

    // 模拟服务方法返回实际空集合,避免IEnumerable模拟的潜在问题
    _getAllTriggerTableService.GetAllTriggerTableDataForOe30Async(testMember.AccountNumber)
        .Returns(Enumerable.Empty<FulfillmentProcess>());

    // 执行被测方法
    var result = await _function.TriggerTableDataAsync(_activityCtx);

    // 验证服务方法被正确调用(用具体参数值替代Arg.Any,测试更严谨)
    await _getAllTriggerTableService.Received()
        .GetAllTriggerTableDataForOe30Async(testMember.AccountNumber);

    // 断言结果非空
    result.Should().NotBeNull();
}

额外优化建议

  • 验证时优先使用具体参数值而非Arg.Any<string>(),确保业务方法正确传递了AccountNumber,提升测试严谨性。
  • 集合类型返回值优先用Enumerable.Empty<T>()或实际列表实例,避免模拟IEnumerable接口带来的不必要问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:32:40