Reputation: 744
I need a little assistance with a strange issue I am facing unit testing a very basic Grails 2.4.1 controller.
Given this controller:
class AuthenticationEventController {
def index() {
// Sorry, ajax only!
if(!request.xhr) {
redirect(controller: "main")
return false
}
render(template: "index")
return
}
}
And this test:
@TestFor(AuthenticationEventController)
class AuthenticationEventControllerSpec extends Specification {
void "Test that the index rejects non-ajax calls"() {
given:
request.isXhr = { false }
when:
controller.index()
then:
response.redirectedUrl == '/main'
}
}
I get a NullPointerException on the "controller.index()" call.
java.lang.NullPointerException
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.codehaus.groovy.grails.orm.support.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:85)
at au.com.intrinsicminds.advansys.controller.AuthenticationEventControllerSpec.Test that the index rejects non-ajax calls(AuthenticationEventControllerSpec.groovy:17)
Upvotes: 10
Views: 3071
Reputation: 11
I got same stacktrace when tried to Spy Transactional service.
I found solution that helps me. So I just init transactionManager in spied service.
See example:
SomeTransactionalService sts = Spy(SomeTransactionalService)
sts.transactionManager = transactionManager // so you need to add init transactionManager
Upvotes: 0
Reputation: 1023
Do you use a domain class anywhere else in your code? I had the same problem (NPE raised by TransactionTemplate#execute) and the solution was to use @Mock to one of my entities, as per this jira issue: https://jira.grails.org/browse/GRAILS-11045
Upvotes: 4
Reputation: 281
the problem most likely is you are using
import grails.transaction.Transactional
instead of
import org.springframework.transaction.annotation.Transactional
for @Transactional
annotation in the groovy class.
why, no clear answer as to the major difference or why the test doesn't do well with this. Also this usually only happens if you are testing a class with 2 more class layers behind it.
Upvotes: 26
Reputation: 27245
The following will work with Grails 2.4.1.
A controller:
// grails-app/controllers/demo/AuthenticationEventController.groovy
package demo
class AuthenticationEventController {
def index() {
if(!request.xhr) {
redirect(controller: "main")
} else {
render(template: "index")
}
}
}
A unit test:
// test/unit/demo/AuthenticationEventControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(AuthenticationEventController)
class AuthenticationEventControllerSpec extends Specification {
void "Test that the index redirects for non-ajax calls"() {
when:
controller.index()
then:
response.redirectedUrl == '/main'
}
void "Test that index renders template for ajax calls"() {
given:
request.makeAjaxRequest()
views['/authenticationEvent/_index.gsp'] = 'my template text'
when:
controller.index()
then:
response.contentAsString == 'my template text'
}
}
I hope that helps.
Upvotes: 0