已配置Mock,为何GetUserByUsernameAndPassword()仍返回null?
已配置Moq Mock但GetUserByUsernameAndPassword仍返回null的原因及解决办法
1. 核心问题:误用未配置的Mock实例
你在测试代码里犯了关键错误:配置好Mock对象后,实例化UserService时用了全新的未配置Mock。
看测试里的这段代码:
// 这里创建并配置了一个Mock<IUserRepository> var userRepository = new Mock<IUserRepository>() .Setup(_ => _.GetUserByUsernameAndPassword(It.IsAny<string>(), It.IsAny<string>())) .Returns(new User { Password = "b", EmailAddress = "asdadsa!yaho", Name = "asa" }); // 但这里却新建了一个空的Mock实例传给UserService,之前配置的完全没用到! var userService = new UserService(new Mock<IUserRepository>().Object);
正确做法是把已经配置好的Mock实例传给UserService,也就是用userRepository.Object代替新创建的Mock。
2. 额外注意:密码参数的匹配问题
业务方法中调用GetUserByUsernameAndPassword时,第二个参数是userCredential.Password.DoHash(),而你测试里传入的密码是"b",Mock中设置的返回用户密码是"b"。如果DoHash()会改变密码值,那么即使Mock配置正确,参数也可能不匹配导致返回null。
修正后的完整测试代码
[Fact] public async Task RegisterUser_MustReturnPhoneNumberError2() { // 配置Mock并保存实例 var userRepositoryMock = new Mock<IUserRepository>(); userRepositoryMock.Setup(_ => _.GetUserByUsernameAndPassword( It.IsAny<string>(), // 如果知道DoHash()的结果,可以写具体值,比如假设DoHash("b")返回"hashed_b" // It.Is<string>(p => p == "hashed_b") It.IsAny<string>() )) .Returns(new User { Password = "b", // 或者这里改成哈希后的值,和业务逻辑一致 EmailAddress = "asdadsa!yaho", Name = "asa" }); // 使用配置好的Mock实例 var userService = new UserService(userRepositoryMock.Object); var expectation = new UserResponseDto { Status = new StatusMaker().ErrorStatus("TEXT") }; var a = new UserCredentialRequestDto { EmailAddress = "a", Password = "b", PhoneNumber = "c" }; var res = await userService.LoginUser(a); Assert.Equal(expectation.Status.Message, res.Status.Message); }
补充说明
- 如果你想让Mock更严谨,可以把
It.IsAny<string>替换为实际调用时的参数值,比如电话号码"c"和密码哈希后的结果。 - 业务方法中的
LoginUser标记为async,但内部调用的是同步的GetUserByUsernameAndPassword,如果实际仓储方法是异步的(比如返回Task<User>),还需要调整Mock的ReturnsAsync而不是Returns。
内容的提问来源于stack exchange,提问作者Masoud
相关产品推荐
相关产品推荐

