unit-testinggrailsgrails-2.5

How to mock springSecurityService in an unit test


I am unit testing a Grails controller method that internally creates an user instance. User domain class uses the springSecurityService of the Spring Security plugin to encode the password before inserting it into the database.

Is there a way to mock that springSecurityService from my unit test in order to get rid of that error?

 Failure:  Create new individual member(MemberControllerSpec)
|  java.lang.NullPointerException: Cannot invoke method encodePassword() on null object

Please find my unit test below.

@TestMixin(HibernateTestMixin)
@TestFor(MemberController)
@Domain([User, IndividualPerson])
class MemberControllerSpec extends Specification {

void "Create new individual member"() {

    given:
    UserDetailsService userDetailsService = Mock(UserDetailsService)
    controller.userDetailsService = userDetailsService

    def command = new IndividualPersonCommand()
    command.username = 'scott@tiger.org'
    command.password = 'What ever'
    command.firstname = 'Scott'
    command.lastname = 'Tiger'
    command.dob = new Date()
    command.email = command.username
    command.phone = '89348'
    command.street = 'A Street'
    command.housenumber = '2'
    command.postcode = '8888'
    command.city = 'A City'

    when:
    request.method = 'POST'
    controller.updateIndividualInstance(command)

    then:
    view == 'createInstance'

    and:
    1 * userDetailsService.loadUserByUsername(command.username) >> null

    and:
    IndividualPerson.count() == 1

    and:
    User.count() == 1

    cleanup:
    IndividualPerson.findAll()*.delete()
    User.findAll()*.delete()
}
}

Solution

  • You can to use this code to encode password in User:

    def beforeInsert() {
        encodePassword()
    }
    
    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }
    
    protected void encodePassword() {
        password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
    }
    

    When springSecurityService is null, encodePassword is not called and NPE is not raised