I'm using Spring security and would like to unit test the password returned by my service. However, as this is encrypted, I'm trying to mock the method that does this encription which is inside the class which extends from WebSecurityConfigurerAdapter.
@Override
public void configure(AuthenticationManagerBuilder auth){
auth.userDetailsService(userDetailsService).passwordEncoder(NoOpPasswordEncoder.getInstance());
}
So I'm trying something like this
@Autowired
AuthenticationManagerBuilder auth;
static class PasswordEncoderTest implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return charSequence.toString().equals(s);
}
}
@Test
void testCreateUser() throws Exception {
UserCreateDto userCreateDto = new UserCreateDto("user", "test", "[email protected]", "[email protected]", "123456", "basic");
User userMocked = new User(userId, "user", "test", "[email protected]", "[email protected]", "123456", "basic");
PasswordEncoderTest passwordEncoderTest = new PasswordEncoderTest();
passwordEncoderTest.encode("123456");
when(auth.userDetailsService(myUserDetailsService).passwordEncoder(NoOpPasswordEncoder.getInstance())).thenReturn(auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoderTest));
userCreateDto = userCommandService.createUser(userCreateDto);
assertEquals(userMocked.getPassword(), userCreateDto.getPassword());
}
But it fails with DaoAuthenticationConfigurer cannot be returned by generateToken() generateToken() should return String
Not sure if the approach is correct and if it is what I may be doing wrong.
Thank you.
UPDATE
https://github.com/francislainy/adverts-backend/tree/dev_jwt
Based on my conversation with Plalx, It seems I should be injecting password encoder rather than bycript and have different configurations between the main and test classes. Will try that and get back here with further updates.
It's working now. Rather than mocking the hashing, having two different beans, one under Configuration
and the other under TestConfiguration
did the trick. The bean for the tests doesn't not have hashing.
Config for the main application:
@Configuration
public class WebConfig {
@Bean public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Config for the tests:
@TestConfiguration
public class TestConfig {
@Bean public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance() ;
}
}
Test:
@Import({TestConfig.class})
@WebMvcTest(UserCommandService.class)
class UserCommandServiceTest {
@MockBean
UserRepository userRepository;
@Autowired
private UserCommandService userCommandService;
@MockBean
private MyUserDetailsService myUserDetailsService;
@MockBean
private JwtUtil jwtUtil;
@Test
void testCreateUser() {
User userMocked = new User(userId, "user", "test", "[email protected]", "123456", "[email protected]", "basic");
UserCreateDto userCreateDto = new UserCreateDto("user", "test", "[email protected]", "123456", [email protected]", "basic");
when(userRepository.save(any(User.class))).thenReturn(userMocked);
userCreateDto = userCommandService.createUser(userCreateDto);
assertEquals(userMocked.getPassword(), userCreateDto.getPassword());
}
}
PS: Don't forget to @Import the TestConfig class above the class name.
And finally the Service class
@Service
public class UserCommandServiceImpl implements UserCommandService {
private final UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public UserCommandServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserCreateDto createUser(UserCreateDto userCreateDto) {
User user = new User();
user.setFirstname(userCreateDto.getFirstname());
user.setLastname(userCreateDto.getLastname());
user.setEmail(userCreateDto.getEmail());
user.setUsername(userCreateDto.getUsername());
user.setPassword(userCreateDto.getPassword());
user = userRepository.save(user);
return new UserCreateDto(user.getId(), user.getFirstname(), user.getLastname(), user.getUsername(), passwordEncoder.encode(user.getPassword()), user.getEmail(), user.getRole());
}
}