2014-10-10 15:31:11

Today I had a very puzzling Exception case in a Spock unit test for LittleGoblin:

void "happyPathTest"() {

given:
def accountResult = userAccountService.createUserAccount('a username', 'a password',
'email@example.com')

expect:
accountResult.isOkay()

}

was giving an NPE in the line with 'def accountResult'.

After making sure that the userAccountService was not null, I checked the return value of createUserAccount - which looks like this:

package de.dewarim.goblin

import grails.transaction.Transactional

@Transactional
class UserAccountService {

AccountCreationResult createUserAccount(String username, String password, String email){
try {
UserAccount newAccount = new UserAccount(username: username, email: email, userRealName: username)
newAccount.passwd = password
newAccount.save()
Role role = Role.findByName('ROLE_USER')
UserRole userRole = new UserRole(newAccount, role)
userRole.save()
return new AccountCreationResult(userAccount: newAccount)
}
catch (Exception e){
log.debug("Failed to create account: "+e.getMessage())
return new AccountCreationResult(errorMessage: e.getMessage())
}
}
}

So, due to the try...catch block, the method should _always_ return an object, never null.

After searching for quite some time I came upon the JIRA entry:

Unit test of service doesn't work with @Transactional annotation

Turns out, you need to add @Mock([...]) for all domain objects used in the service method along with mocking the transactionManager for the service in the tests setup().

userAccountService.transactionManager = Mock(PlatformTransactionManager) {
getTransaction(_) >> Mock(TransactionStatus)
}