使用Mockito时变量值无法覆写的问题求助
问题:Mockito无法模拟save方法返回null属性的对象
我在测试followedByEntity为null的异常场景时,发现Mockito无法正确让userRepository.save()返回该属性为null的对象——即使尝试了when..Return()、doReturn()等方法,该属性始终不为null。只有把整个对象设为null,或者把逻辑抽成方法用Spy模拟才能生效,怀疑是对Mockito用法有误解。
业务代码
@Mock UserRepository userRepository; @Spy @InjectMocks UserServiceImpl userService; @Override public void followUser(UUID fromId, UUID toId) throws FollowerNotFoundException { Optional<UserEntity> userEntityOptionalFrom = userRepository.findById(fromId); Optional<UserEntity> userEntityOptionalTo = userRepository.findById(toId); if (userEntityOptionalFrom.isEmpty() || userEntityOptionalTo.isEmpty()) { throw new UserNotFoundException("No user found with this id"); } UserEntity userEntityTo = userEntityOptionalTo.get(); UserEntity userEntityFrom = userEntityOptionalFrom.get(); Set<FollowingRequestEntity> followingRequestEntities = new HashSet<>(); FollowingRequestEntity followingRequestEntity = FollowingRequestEntity.builder().userSenderEntity(userEntityFrom).userReceiverEntity(userEntityTo).build(); followingRequestEntities.add(followingRequestEntity); userEntityTo.setFollowedByEntity(followingRequestEntities); userEntityTo = userRepository.save(userEntityTo); if (userEntityTo.getFollowedByEntity() == null || userEntityTo.getFollowedByEntity().isEmpty()) { throw new FollowerNotFoundException("Follower Not Found"); } } public UserEntity setFollower(UserEntity userEntityTo, UserEntity userEntityFrom) { // 调用并Mock这个方法时测试能生效 Set<FollowingRequestEntity> followingRequestEntities = new HashSet<>(); FollowingRequestEntity followingRequestEntity = FollowingRequestEntity.builder().userSenderEntity(userEntityFrom).userReceiverEntity(userEntityTo).build(); followingRequestEntities.add(followingRequestEntity); userEntityTo.setFollowedByEntity(followingRequestEntities); return userEntityTo; }
测试代码(原代码)
@Test void testFollowUser_ThrowsExceptionWhenFollowerIsFound() { UUID userFromId = randomUUID(); UUID userToId = randomUUID(); UserEntity userEntityFrom = getUserEntity(); userEntityFrom.setId(userFromId); UserEntity userEntityTo = getUserEntity(); userEntityTo.setId(userToId); userEntityTo.setName("new name"); when(userRepository.findById(userEntityFrom.getId())).thenReturn(Optional.of(userEntityFrom)); when(userRepository.findById(userEntityTo.getId())).thenReturn(Optional.of(userEntityTo)); // when(userRepository.save(userEntityTo)).thenReturn(userEntityTo); userEntityTo.setFollowerOfEntity(null); userEntityTo.setFollowedByEntity(null); doReturn(userEntityTo).when(userRepository).save(any()); // when(userEntityTo.getFollowedByEntity()).thenReturn(null); // doReturn(userEntityTo).when(userService).setFollower(any(), any()); FollowerNotFoundException exception = assertThrows(FollowerNotFoundException.class, () -> userService.followUser(userFromId, userToId)); assertEquals("Follower Not Found", exception.getMessage()); }
问题原因
核心问题是对象引用复用:你在测试中修改的userEntityTo和业务方法中被操作的是同一个实例。业务方法里会先执行userEntityTo.setFollowedByEntity(followingRequestEntities)给这个对象的属性赋值,之后才调用save()。而你Mock的save()返回的就是这个已经被修改过的对象,所以followedByEntity自然不为null。
解决方案
创建一个独立的新UserEntity实例作为save()方法的返回值,将其followedByEntity设为null,其他属性和原对象保持一致即可。
修改后的测试代码
@Test void testFollowUser_ThrowsExceptionWhenFollowerIsFound() { UUID userFromId = randomUUID(); UUID userToId = randomUUID(); // 准备findById返回的原对象 UserEntity userEntityFrom = getUserEntity(); userEntityFrom.setId(userFromId); UserEntity userEntityTo = getUserEntity(); userEntityTo.setId(userToId); userEntityTo.setName("new name"); // 准备save方法返回的对象:复制原对象属性,仅将followedByEntity设为null UserEntity savedUser = getUserEntity(); savedUser.setId(userToId); savedUser.setName("new name"); savedUser.setFollowerOfEntity(null); savedUser.setFollowedByEntity(null); // Mock findById方法 when(userRepository.findById(userFromId)).thenReturn(Optional.of(userEntityFrom)); when(userRepository.findById(userToId)).thenReturn(Optional.of(userEntityTo)); // Mock save方法,返回我们预先准备好的、followedByEntity为null的对象 doReturn(savedUser).when(userRepository).save(any(UserEntity.class)); // 验证异常抛出 FollowerNotFoundException exception = assertThrows( FollowerNotFoundException.class, () -> userService.followUser(userFromId, userToId) ); assertEquals("Follower Not Found", exception.getMessage()); }
说明
业务方法中userEntityTo = userRepository.save(userEntityTo)会把变量指向我们新创建的对象,此时该对象的followedByEntity为null,后续的判断逻辑就会触发FollowerNotFoundException,符合你的测试预期。
内容的提问来源于stack exchange,提问作者Francislainy Campos
相关产品推荐
相关产品推荐

