### Question:
LibraryUserDetailsService implements UserDetailsService, UserDetailsPasswordService { @Override public UserDetails updatePassword(UserDetails user, String newPassword) { return userService .findOneByEmail(user.getUsername()) .map( u -> { LOGGER.info( "Upgrading password {} for user {} to {}", user.getPassword(), user.getUsername(), newPassword); u.setPassword(newPassword); return new AuthenticatedUser(userService.save(u)); }) .orElseThrow( () -> new UsernameNotFoundException("No user found for " + user.getUsername())); } LibraryUserDetailsService(UserService userService); @Override UserDetails loadUserByUsername(String username); @Override UserDetails updatePassword(UserDetails user, String newPassword);  }### Answer:
@DisplayName("can update password for existing user") @Test void updatePassword() { User user = new User("Hans", "Test", "test@example.com", "secret", Collections.singleton("USER")); UserDetails userDetails = new AuthenticatedUser(user); given(userService.findOneByEmail(any())).willReturn(Optional.of(user)); given(userService.save(any())) .willReturn( new User( "Hans", "Test", "test@example.com", "newpassword", Collections.singleton("USER"))); UserDetails result = cut.updatePassword(userDetails, "newpassword"); assertThat(result) .isNotNull() .isInstanceOf(AuthenticatedUser.class) .extracting(UserDetails::getPassword) .isEqualTo("newpassword"); }
@DisplayName("reports expected error when password could not be updated") @Test void updatePasswordUsernameNotFound() { User user = new User("Hans", "Test", "test@example.com", "secret", Collections.singleton("USER")); UserDetails userDetails = new AuthenticatedUser(user); given(userService.findOneByEmail(any())).willReturn(Optional.empty()); assertThatExceptionOfType(UsernameNotFoundException.class) .isThrownBy(() -> cut.updatePassword(userDetails, "newpassword")) .withMessage("No user found for test@example.com") .withNoCause(); }