NullpointerException: cannot get property on null

2019-07-20 10:29发布

问题:

Working on IDEA and trying to launch the following code:

package com.myCompany.routing.spring

import com.dropbox.core.DbxRequestConfig
import grails.util.Holders
import spock.lang.Specification

class DropboxSpringConfigSpec extends Specification {
    def grailsApplication=Holders.grailsApplication

    def "It instantiates and configures the dropboxRequestConfig component"() {
        given:
        def ctx = grailsApplication.mainContext
        //do stuff...
    }
}

I get the following error:

java.lang.NullPointerException: Cannot get property 'mainContext' on null object

at com.myCompany.routing.spring.DropboxSpringConfigSpec.It instantiates and configures the dropboxRequestConfig component(DropboxSpringConfigSpec.groovy:20)

I've recently made a pull on my VCS, so the code should work.

When running the test as Grails test, I get the following error:

Error | 2015-03-04 13:32:00,989 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: Missing configuration in Config.groovy: connection.uri.

回答1:

Okay, it seems some configurations in Config.groovy were given the values of some environment variables:

elasticSearch {
    connection {
        uri = env.ES_URL
        username = env.ES_USER
        password = env.ES_PASSWORD
    }
    indexPrefix = 'test-'
}

Since I never created the corresponding environment variables, the GrailsContextLoader fails to find the corresponding value and the computation fail.

Initializing the required environmnent variables in my IDE and running the tests as Grails tests solved the problem.



回答2:

By your extends Specification seems that what you have there is a unit test. grailsApplication is not available on unit specs, though it can be mocked (ie. using the @TestFor(ClassUnderTest) annotation mockes it up for you).

If what you want to test is configuration I would recommend writing an integration spec. On the integration phase, you basically have a wired grails application without the web interface. In that case all you'll need would be to do is

package com.myCompany.routing.spring

import com.dropbox.core.DbxRequestConfig
import grails.util.Holders
import grails.test.spock.IntegrationSpec

class DropboxSpringConfigSpec extends IntegrationSpec {
    def grailsApplication //This will be auto-wired 

    def "It instantiates and configures the dropboxRequestConfig component"() {
        given:
        def ctx = grailsApplication.mainContext
        //do stuff...
    }
}

Re that test having worked previously in your VCS. I've never used Holders on a unit spec, so I cannot really say it wouldn't work, but it may have just been a false positive. From my understanding on the unit phase you don't have a running grails application and beans (including config) would not be available until mocked by you or the testing framework (again, using @TestFor or @Mock)