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

如何对返回ArgumentException的MediatR方法进行单元测试

问题根因

你遇到的报错是两个错误叠加导致的:

  1. 你写的回调是同步委托,userDefinitionRepository.Create(user) 抛出的 ArgumentException 会直接在同步执行阶段抛出,被Moq识别为Mock构造过程的异常,不会作为IMediator.Send方法返回的Task的异常透出
  2. t as Task<Unit> 的转换写法存在缺陷:只要Create方法的返回值不是Task<Unit>类型,as转换会直接返回null,后续await这个返回值时就会触发空引用异常,完全覆盖了你预期的ArgumentException。

正确实现方案

方案1:需要在Send回调中执行Create逻辑

把回调改为异步委托,不需要手动做Task类型转换,异常会自动封装到返回的Task中:

_mediatorMock.Setup(m => m.Send(It.IsAny<UpdateUserCommand>(), It.IsAny<CancellationToken>()))
    .Returns(async (UpdateUserCommand command, CancellationToken cancel) => 
    {
        // 此处抛出的ArgumentException会被自动封装到Task<Unit>中
        userDefinitionRepository.Create(user);
        return Unit.Value;
    });

方案2:仅模拟Send抛出预期异常(不需要实际调用Create)

直接用Moq提供的ThrowsAsync方法更简洁:

_mediatorMock.Setup(m => m.Send(It.IsAny<UpdateUserCommand>(), It.IsAny<CancellationToken>()))
    .ThrowsAsync(new ArgumentException("你的预期异常信息"));

异常验证写法

调用控制器方法时,用测试框架的异常断言校验即可,以xUnit为例:

// 校验调用Post方法时确实抛出了ArgumentException
var exception = await Assert.ThrowsAsync<ArgumentException>(() => controller.Post(2, cmd));
// 可选:校验异常的参数名、消息等是否符合预期
Assert.Equal("你预期报错的参数名", exception.ParamName);

内容的提问来源于stack exchange,提问作者this-Me

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:45:08