Reputation: 75
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.
Upvotes: 0
Views: 1275
Reputation: 77167
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]
Upvotes: 3