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

外部服务方法Mock失效,调用后返回Null问题求助

排查Mock AssignOrderReserve方法返回Null的原因

问题背景

测试中对ISupplyReservesClient的AssignOrderReserve方法做了Mock配置,但运行测试时Mock始终失效,返回Null。相关代码如下:

业务代码中调用的方法

AssignOrderReserveCommandResponseDto response = await _supplyReservesClient.AssignOrderReserve(
    masterReserveId,
    inboundReserveId,
    deliveryDate,
    orderInfos,
    cancellationToken)

当前Mock实现

public static readonly ISupplyReservesClient SupplyReservesClient = Substitute.For<ISupplyReservesClient>();
public static AssignOrderReserveCommandResponseDto assignOrderReserveCommandResponse;

static SupplyReservesClientMock()
{
    SupplyReservesClient
         .AssignOrderReserve(Arg.Any<Guid>(), Arg.Any<Guid>(),
             Arg.Any<DateTimeOffset>(), Arg.Any<IReadOnlyCollection<AssignOrderInfo>>(),
             Arg.Any<CancellationToken>())
         .Returns(_ => assignOrderReserveCommandResponse);
}

public static void SetAssignOrderReserveCommandResponseDto(long bidId, long otherBidId)
{
    Fixture fixture = new Fixture();
    assignOrderReserveCommandResponse = fixture.Build<AssignOrderReserveCommandResponseDto>()
        .With(x => x.OrderInfos, new List<AssignOrderReserveCommandResponseDto.OrderInfo>()
        {
            new(bidId, "1", DateTime.UtcNow.AddDays(3)),
            new(otherBidId, "1", DateTime.UtcNow.AddDays(3))
        })
        .With(x => x.InboundReserveId, fixture.Create<Guid>())
        .Create();
}

待Mock的目标方法内部逻辑

public async Task<AssignOrderReserveCommandResponseDto> AssignOrderReserve(
    Guid? masterReserveId,
    Guid? inboundReserveId,
    DateTimeOffset deliveryDate,
    IReadOnlyCollection<AssignOrderInfo> orderInfos,
    CancellationToken cancellationToken)
{
    AssignOrderReserveCommand command = AssignOrderReserveConverter
        .Convert(masterReserveId, inboundReserveId, deliveryDate, orderInfos);

    AssignOrderReserveCommandResponse response = await _supplyReservesClient
        .AssignOrderReserveAsync(command, cancellationToken: cancellationToken);

    return AssignOrderReserveConverter.Convert(response);
}

核心失效原因

1. Mock的方法与实际执行的方法不匹配

从目标方法的内部逻辑能明确看到:上层代码调用的AssignOrderReserve方法,内部实际转调了AssignOrderReserveAsync方法,而非直接调用外部服务的AssignOrderReserve。但你的Mock仅针对AssignOrderReserve做了配置,完全没处理AssignOrderReserveAsync,导致这个未被Mock的方法返回默认值Null,最终整个流程返回Null。

2. 参数类型匹配错误(次要但需修正)

目标方法中masterReserveId和inboundReserveId的类型是Guid?(可空Guid),但Mock配置中用的是Arg.Any<Guid>()(非空Guid)。如果业务代码中传入的是null值,参数匹配条件会不满足,同样会导致Mock失效返回Null。


修正后的Mock实现示例

public static readonly ISupplyReservesClient SupplyReservesClient = Substitute.For<ISupplyReservesClient>();
public static AssignOrderReserveCommandResponse assignOrderReserveCommandResponse; // 类型改为CommandResponse

static SupplyReservesClientMock()
{
    // 修正1:Mock实际调用的AssignOrderReserveAsync方法
    SupplyReservesClient
         .AssignOrderReserveAsync(Arg.Any<AssignOrderReserveCommand>(), Arg.Any<CancellationToken>())
         .Returns(_ => assignOrderReserveCommandResponse);

    // 可选:保留原AssignOrderReserve的Mock,修正参数类型为可空Guid
    SupplyReservesClient
         .AssignOrderReserve(Arg.Any<Guid?>(), Arg.Any<Guid?>(),
             Arg.Any<DateTimeOffset>(), Arg.Any<IReadOnlyCollection<AssignOrderInfo>>(),
             Arg.Any<CancellationToken>())
         .Returns(async (Guid? m, Guid? i, DateTimeOffset d, IReadOnlyCollection<AssignOrderInfo> o, CancellationToken ct) => 
         {
             var command = AssignOrderReserveConverter.Convert(m, i, d, o);
             var resp = await SupplyReservesClient.AssignOrderReserveAsync(command, ct);
             return AssignOrderReserveConverter.Convert(resp);
         });
}

public static void SetAssignOrderReserveCommandResponse(long bidId, long otherBidId)
{
    Fixture fixture = new Fixture();
    // 修正:构造AssignOrderReserveCommandResponse实例(而非Dto)
    assignOrderReserveCommandResponse = fixture.Build<AssignOrderReserveCommandResponse>()
        .With(x => x.OrderInfos, new List<AssignOrderReserveCommandResponse.OrderInfo>()
        {
            new(bidId, "1", DateTime.UtcNow.AddDays(3)),
            new(otherBidId, "1", DateTime.UtcNow.AddDays(3))
        })
        .With(x => x.InboundReserveId, fixture.Create<Guid>())
        .Create();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:16:05