I am learning Spock framework. I have trouble with implementing some test to my project.
I write test to REST API save method :
@Override
public User save(User user) {
roleRepository.findByName("ROLE_USER").ifPresent(role ->
user.setRoles(Collections.singletonList(role)));
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
And my test class looks like this :
class UserServiceImplSpec extends Specification {
def userService
def userRepository = Mock(UserRepository)
def passwordEncoder = Mock(PasswordEncoder)
def roleRepository = Mock(RoleRepository)
def setup() {
userService = new UserServiceImpl(userRepository, passwordEncoder, roleRepository)
}
def 'should save user'() {
given:
def user = new User()
when:
userService.save(user)
then:
1 * roleRepository.findByName('ROLE_USER')
1 * passwordEncoder.encode(user.getPassword())
1 * userRepository.save(user)
0 * _
}
}
After running test I have error:
java.lang.NullPointerException
at com.jakub.shop.service.impl.UserServiceImpl.save(UserServiceImpl.java:28)
at com.jakub.shop.service.impl.UserServiceImplSpec.should save user(UserServiceImplSpec.groovy:47)
I know that i have to mock something into my roleRepository, but I dont have a clue what. Propably list of roles. I tried in many ways but it did not work. What should I do to write this test correct? I know that my rest method is written properly.
You're not returning anything from your findByName
or encode
calls. You should be returning appropriate values and checking that they're used properly, something like this:
def 'should save user'() {
given:
def user = new User()
final String encodedPassword = 'pAsSwOrD'
User saved
when:
userService.save(user)
then:
1 * roleRepository.findByName('ROLE_USER') >> Optional.empty()
1 * passwordEncoder.encode(user.password) >> encodedPassword
1 * userRepository.save(_) >> { saved = it[0] }
0 * _
and:
encodedPassword == saved.password
saved.roles.empty
}
Note also that you don't need a setup
method; you can just say
@Subject
UserServiceImpl userService = new UserServiceImpl(userRepository, passwordEncoder, roleRepository)
Even better, you might want to take a look at the documentation for data-driven testing and have multiple test cases like this:
where:
userRole || expected
null || emptyList()
ROLE_OBJ || [ROLE_OBJ]