Search code examples
unit-testinggrailsdependency-injectionspock

Grails Unit Test does not work when dependency inject is necessary


I am trying to run my unit tests in Grails 4.0.3 through the command grails test-app.

Unfortunately I am in trouble with dependency injection.

I have basically two test cases. The first one does not work with the response No GORM implementations configured. Ensure GORM has been initialized correctly It seems that PidService is not correctly injected.

To demonstrate my suspicion I created a private method which only throws an exception, to be invoked in the second test case. So, I invoked that method in the second one and it worked as expected. The exception was correctly catched and I could verify that the message is correct.

package br.gov.cmb.pid.tests

import br.gov.cmb.pid.services.PidService
import grails.testing.services.ServiceUnitTest
import org.grails.web.json.JSONObject
import spock.lang.Specification


class PidIssuingSpec extends Specification implements ServiceUnitTest<PidService> {

    def setup() {
    }

    def cleanup() {
    }


    def "Test that injection is not working"() {
        given:
        JSONObject wrongPidIssuingDocument = new JSONObject()

        when:
        service.buildPidIssuingOrder(wrongPidIssuingDocument)

        then:
        def e = thrown(Exception)
        e.message == "Register number is mandatory."
    }


    def "Test that works because no injection is necessary"(){
        when:
        dispException()

        then:
        def e = thrown(Exception)
        e.message == "Register number is mandatory."
        println(e.message)

    }

    private void dispException(){
        throw new Exception("Register number is mandatory.")
    }
}

Solution

  • Grails Unit Test does not work when dependency inject is necessary

    In general unit tests that require dependency injection is supported.

    See the Modifying the Application Context section at https://testing.grails.org/2.4.1/guide/index.html#unitTesting. That demonstrates how to add beans to the context in a unit test so they may be injected. For example, you could do this:

    Closure doWithSpring() {{ ->
        // create a bean named "someService" which
        // is an instance of SomeService.
        // the someService bean may be injected into the 
        // the class under test
        someService(SomeService)
    }}
    

    At https://github.com/grails/grails-testing-support/blob/9f782ff3b911919e421440feb8a2e4736c6aced6/examples/demo33/src/test/groovy/demo/ReportingServiceSpec.groovy is a working example:

    package demo
    
    import grails.testing.services.ServiceUnitTest
    import spock.lang.Specification
    
    class ReportingServiceSpec extends Specification implements ServiceUnitTest<ReportingService> {
    
        Closure doWithSpring() {{ ->
            someHelper RushHelper
        }}
    
        void "test dependency injection"() {
            expect:
            service.retrieveSomeNumber() == 2112
        }
    }
    
    class RushHelper implements MathHelper {
    
        @Override
        int getSomeNumber() {
            2112
        }
    }
    

    Notice that the service being tested is the ReportingService. The RushHelper is being injected into that service to support the test.