J'ai une implémentation de l'interface Spring UserDetailsService
:Je ne peux pas réécrire test unitaire Mockito à Spock Spécification
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final UserEntity user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Cannot find user with username " + username);
}
return new User(user);
}
}
UserRepository
est une interface standard extendng JpaRepository<UserEntity, Long>
où UserEntity
est ma classe de modèle. Est une implémentation de UserDetails
de Spring Framework.
Et j'ai écrit un test unitaire pour cette méthode en utilisant JUnit et Mockito. Ces tests fonctionnent:
@RunWith(SpringRunner.class)
@DirtiesContext
public class UserDetailsServiceTest {
@Autowired
private UserDetailsService userDetailsService;
@Test
public void shouldFindUser() throws Exception {
// given
final UserEntity user = new UserEntity(
1L,
"username",
"[email protected]",
"password",
new ArrayList<>() // list of roles
);
when(UserDetailsServiceTestContext.userRepository.findByUsername(user.getUsername()))
.thenReturn(user);
// when
final UserDetails result = userDetailsService.loadUserByUsername(user.getUsername());
// then
assertThat(result).isEqualTo(UserFactory.create(user));
verify(UserDetailsServiceTestContext.userRepository)
.findByUsername(user.getUsername());
}
@Test(expected = UsernameNotFoundException.class)
public void shouldNotFindUser() throws Exception {
// given
when(UserDetailsServiceTestContext.userRepository.findByUsername(anyString()))
.thenReturn(null);
// when
final UserDetails result = userDetailsService.loadUserByUsername(new String());
}
@TestConfiguration
static class UserDetailsServiceTestContext {
@MockBean
private static UserRepository userRepository;
@Bean
UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl(userRepository);
}
}
}
Et maintenant j'essaye d'écrire ces tests en utilisant le framework Groovy et Spock. J'ai écrit la spécification suivante:
def 'should find user'() {
given:
def user = new UserEntity(
1L,
"username",
"[email protected]",
"password"
new ArrayList<>() // list of roles
)
userRepository.findByUsername(user.username) >> user
// userRepository.findByUsername(_ as String) >> user // also working
when:
def result = userDetailsService.loadUserByUsername(user.username)
then:
result == new User(user)
}
et ce test fonctionne. Mais quand je veux vérifier l'appel de userRepository par ajouter dans la section then:
une déclaration 1 * userRepository.findByUsername(user.username)
ou 1 * userRepository.findByUsername(_ as String)
j'obtiens une erreur UserDetailsServiceSpec.should find user and return new User:36 » UsernameNotFound
. ligne 36 est dans la section when: