如何用Moq和xUnit对Web API的Delete操作进行单元测试?
解决Web API Delete操作单元测试失败的问题
你的测试失败原因很明确:控制器的DeleteCompany方法会先调用GetCompanyById检查数据是否存在,但你只Mock了DeleteCompany方法,没对GetCompanyById做任何设置,Moq默认会返回null,导致控制器直接进入NotFound分支,返回404,而不是预期的204。
修正步骤:
- Mock
GetCompanyById方法,让它返回一个有效的Company实例,确保控制器能进入删除逻辑分支 - 修正结果类型断言:控制器执行成功后返回的是
NoContentResult,不是OkObjectResult,强转类型错误会直接抛出异常 - 验证
DeleteCompany是否被调用,确保删除逻辑确实被执行
修正后的测试代码:
[Theory] [InlineData(1)] public async Task CompanyController_DeleteCompany_ShouldReturnStatusCode204(int id) { // 创建模拟的Company对象 var mockCompany = new Company { Id = id, Name = "Test Company" }; var mockRepo = new Mock<ICompanyRepository>(); // Mock GetCompanyById方法,返回模拟对象 mockRepo.Setup(repo => repo.GetCompanyById(id)) .ReturnsAsync(mockCompany); // Mock DeleteCompany方法 mockRepo.Setup(repo => repo.DeleteCompany(id)) .Returns(Task.CompletedTask) .Verifiable(); var sut = new CompanyController(mockRepo.Object); // 执行方法并转换为正确的结果类型 var result = await sut.DeleteCompany(id); var noContentResult = result as NoContentResult; // 断言状态码为204 noContentResult.StatusCode.Should().Be(204); // 验证DeleteCompany是否被调用过一次 mockRepo.Verify(repo => repo.DeleteCompany(id), Times.Once); }
额外说明:
- 若要测试"当公司不存在时返回NotFound"的场景,可以单独写测试用例:Mock
GetCompanyById返回null,断言结果是NotFoundResult - 强转类型时尽量用
as关键字,避免类型不匹配抛出异常,之后再判断是否为null,让测试更健壮
内容的提问来源于stack exchange,提问作者Aboliii
相关产品推荐
相关产品推荐

