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

单元测试中使用Moq模拟服务时触发空引用异常的问题求助

单元测试中使用Moq模拟服务时触发空引用异常的问题求助

嗨,我来帮你排查这个问题~

从你描述的情况和代码来看,空引用异常的根源是Moq的方法匹配没有命中,导致_service.CreateTransactionAsync(payload)返回了默认的null,后续访问res.Status自然就抛出异常了。

问题具体原因

你在Mock设置阶段用的是TransactionFixture.CreateTransaction()创建的一个请求实例,但在调用控制器方法时,又重新调用了一次TransactionFixture.CreateTransaction()生成了另一个新的实例。Moq默认采用引用相等匹配,这两个实例是不同的对象,所以Mock不会返回你预设的transactionResponse,最终res变量为null。

修复方案(三种可选)

方案1:匹配任意类型的参数(最简便)

如果你不需要精确匹配请求参数的内容,只需要确保Mock的方法被触发,可以用It.IsAny<T>()来匹配任意TransactionReqDto类型的参数:

// Arrange部分修改Setup代码
mockTransactionService.Setup(service => service.CreateTransactionAsync(It.IsAny<TransactionReqDto>()))
                      .ReturnsAsync(transactionResponse);

方案2:精确匹配参数的属性值

如果需要验证请求参数的具体属性是否符合预期,可以用It.Is<T>()结合断言来匹配:

var expectedRequest = TransactionFixture.CreateTransaction();
mockTransactionService.Setup(service => service.CreateTransactionAsync(It.Is<TransactionReqDto>(req => 
    req.Id == expectedRequest.Id && 
    req.Amount == expectedRequest.Amount // 替换成你需要校验的实际属性
)))
.ReturnsAsync(transactionResponse);

方案3:使用同一个请求实例

确保Setup和Act阶段使用的是同一个TransactionReqDto实例,这样引用匹配就能命中:

// Arrange
var transactionRequest = TransactionFixture.CreateTransaction(); // 只创建一次实例
var transactionResponse = new TransactionResDto { Status = true };
mockTransactionService.Setup(service => service.CreateTransactionAsync(transactionRequest))
                      .ReturnsAsync(transactionResponse);
var mockTransactionController = new TransactionController(mockTransactionService.Object);

// Act
var result = (OkObjectResult) await mockTransactionController.CreateTransaction(transactionRequest); // 复用同一个实例

额外建议

为了确保测试的严谨性,你可以在断言阶段加上对Mock方法调用的验证,确认服务方法确实被调用了:

// Assert部分新增
mockTransactionService.Verify(service => service.CreateTransactionAsync(It.IsAny<TransactionReqDto>()), Times.Once);

备注:内容来源于stack exchange,提问作者Seyi Agboola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:08:09