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)
}