C#中使用Moq模拟MediatR进行集成测试返回null问题排查
问题排查与修复
你的测试返回null且不符合预期的核心原因有两个:
1. Moq未正确匹配MediatR的泛型Send方法
MediatR的IMediator.Send是泛型方法,定义为:
Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default);
你当前的Setup未指定泛型参数,Moq无法识别你要模拟的是返回Result<Unit>的Send调用,实际调用时未触发模拟逻辑,因此返回null。
2. 测试预期对象未正确初始化
你用new Result<Unit>()创建的预期对象未设置Error属性值,即便模拟成功,断言也会失败。应使用Result<Unit>.Failure()静态方法创建符合预期的失败结果。
修复后的测试代码
[TestFixture] public class UserControllerTests { private Mock<IMediator> _mockMediator; private UserController _userController; [SetUp] // 改用SetUp初始化,符合NUnit规范 public void Setup() { _mockMediator = new Mock<IMediator>(); _userController = new UserController(_mockMediator.Object); } [Test] public async Task DeleteUser_NotSuccessful_NoIdDeleted() { // 用Failure方法创建预期的失败结果 var expected = Result<Unit>.Failure("User Id doesn't exsist"); // 指定泛型参数,精准匹配目标Send调用 _mockMediator.Setup(x => x.Send<Result<Unit>>( It.Is<DeleteUserCommand>(cmd => cmd.UserId == 6), It.IsAny<CancellationToken>())) .ReturnsAsync(expected); // 替代Task.FromResult,代码更简洁 var result = await _userController.DeleteUser(6); Assert.AreEqual("User Id doesn't exsist", result.Value.Error); Assert.IsFalse(result.Value.IsSuccess); } [Test] public async Task DeleteUser_Successful_UserIdDeleted() { var expected = Result<Unit>.Success(Unit.Value); _mockMediator.Setup(x => x.Send<Result<Unit>>( It.Is<DeleteUserCommand>(cmd => cmd.UserId == 7), It.IsAny<CancellationToken>())) .ReturnsAsync(expected); var result = await _userController.DeleteUser(7); Assert.IsTrue(result.Value.IsSuccess); Assert.AreEqual(Unit.Value, result.Value.Value); } }
额外优化建议
- 用
[SetUp]替代构造函数初始化测试依赖,更符合测试框架规范且灵活 - 对
DeleteUserCommand的UserId做精准匹配,避免测试逻辑被其他ID的调用干扰 - 使用
ReturnsAsync简化异步返回值的模拟
内容的提问来源于stack exchange,提问作者Sean Elias
相关产品推荐
相关产品推荐

