.NET Core xUnit/Moq API调用单元测试失败问题排查
问题分析与解决方案
嘿,我一眼就瞅出问题所在了——你的测试代码只配置了IRepository的Locations属性,但你的API控制器实际调用的是索引器this[int zip]啊!Moq对于没有显式设置的成员,默认会返回null,这就是为啥你调试时看到仓库里有对象,但result还是null的原因。
具体问题点
你的API核心逻辑用的是索引器获取数据:
Location result = repository[zip];
但测试里只给Locations属性做了配置:
mockRepo.Setup(m => m.Locations).Returns(new Location[] { new Location { zip = 88012, type = "STANDARD", state = "NM" } });
完全没管索引器的行为,Moq自然返回null,控制器就走了NotFound()分支。
另外,你的断言逻辑也有问题:response.Equals(HttpStatusCode.OK)不成立,因为response是IActionResult类型,不是HttpStatusCode,得先把它转换成对应的结果类型再做判断。
修正后的测试代码
[Fact] public void Api_Returns_Json_Object() { // Arrange var testLocation = new Location { zip = 88012, type = "STANDARD", state = "NM" }; Mock<IRepository> mockRepo = new Mock<IRepository>(); // 核心:配置索引器的行为,让它根据传入的zip返回对应对象 mockRepo.Setup(m => m[It.IsAny<int>()]) .Returns((int zip) => zip == 88012 ? testLocation : null); // 如果你的Repository逻辑里Locations和索引器有关联,可以保留原有配置 mockRepo.Setup(m => m.Locations).Returns(new[] { testLocation }); ApiController controller = new ApiController(mockRepo.Object); // Act var response = controller.Get(88012) as OkObjectResult; // Assert Assert.NotNull(response); // 确保返回的是Ok结果而非NotFound Assert.Equal(HttpStatusCode.OK, (HttpStatusCode)response.StatusCode); var returnedLocation = response.Value as Location; Assert.Equal(88012, returnedLocation.zip); Assert.Equal("NM", returnedLocation.state); }
额外说明
- 如果你只需要针对特定zip值做测试,也可以把索引器配置简化成:
mockRepo.Setup(m => m[88012]).Returns(testLocation); - 断言时先转换结果类型再校验,能让测试更严谨,避免因为返回类型不符导致的隐性错误。
内容的提问来源于stack exchange,提问作者coolhand
相关产品推荐
相关产品推荐

