简体   繁体   中英

Nullpointer in simple grails controller unit test

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)

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.

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM