12

I need to get the dependencies injected in my domain objects in my tests.

This tests are placed in the test/integration directory and extends from spock.lang.Specification.

How can I achieve this?

Note: I've seen this post How to inject spring beans into spock test, but it is not related with grails.

Edit:

The dependency I want to get injected is springSecurityService in my SecUser subclass called Player. The method that is failing is the encodePassword(), which is called in the beforeInsert().

I can mock this encodePassword() method in some tests, but when I want to test my controllers method save(), I can't mock the Player that is being created because it all happens inside the controllers method.

After changing to extend IntegrationSpec, this is my test code:

package intertigre.test.domain
import intertigre.domain.Fecha;
import intertigre.test.util.DomainFactoryTestService
import grails.plugin.spock.IntegrationSpec
import grails.test.mixin.TestFor

    @TestFor(Fecha)
    class FechaSpec extends IntegrationSpec{

    DomainFactoryTestService domainFactoryTestService = new DomainFactoryTestService()

    def 'test'(){
        given:
            def fecha = new Fecha()
        when:
            fecha.save()
        then:
            Fecha.get(1) == fecha
    }

}

I'm getting this exception when running grails test-app :spock:

java.lang.NullPointerException: Cannot get property 'mainContext' on null object
    at grails.plugin.spock.IntegrationSpec.$spock_initializeSharedFields(IntegrationSpec.groovy)

And this one when I run the test alone:

| Failure:  intertigre.test.domain.FechaSpec
|  java.lang.NullPointerException: Cannot get property 'autowireCapableBeanFactory' on null object
    at grails.plugin.spock.IntegrationSpec.setupSpec(IntegrationSpec.groovy:47)
| Failure:  intertigre.test.domain.FechaSpec
|  java.lang.NullPointerException: Cannot invoke method isActive() on null object
    at grails.test.mixin.support.GrailsUnitTestMixin.shutdownApplicationContext(GrailsUnitTestMixin.groovy:232)
    at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:176)
    at org.spockframework.runtime.extension.builtin.JUnitFixtureMethodsExtension$FixtureType$FixtureMethodInterceptor.intercept(JUnitFixtureMethodsExtension.java:145)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:84)
    at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:176)
Community
  • 1
  • 1
Tomas Romero
  • 8,418
  • 11
  • 50
  • 72

2 Answers2

12

Try declaring the springSecurityService into the test, as you would do in a controller. Grails is supposed to do all the job for you :)

For an integration test you do something like this:

package intertigre.test.domain
import intertigre.domain.Fecha;
import intertigre.test.util.DomainFactoryTestService
import grails.plugin.spock.IntegrationSpec

class DomainFactoryTestServiceSpec extends IntegrationSpec{

def domainFactoryTestService // you dont need to create a new instance, it's injected by spring

def 'test'(){
     given:
         // ...
     when:
         // ...
     then:
         // ....
 }

If you need to test a specific domain object (as your Fecha class), you probably need a unit test, something like this:

package intertigre.test.domain
import intertigre.domain.Fecha
import intertigre.test.util.DomainFactoryTestService
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification

@TestFor(Fecha)
@Mock([OtherObject1, OtherObject2])
class FechaSpec extends Specification {

def domainFactoryTestService // same thing here, if you need the service

def 'test'() {
     given:
         def fecha = new Fecha()
     and:
         def oo1 = new OtherObject1()
     when:
         // ...
     then:
         // ....
 }

You can use unit test to test services as well, it depends on what are you going to test (a class -the service- or a "situation" -the way the service is used-).

Ps. Of course, this code here hasn't been tested and can contain typos. :) But I hope you get my point about how to test.

lucke84
  • 4,516
  • 3
  • 37
  • 58
  • I'm actually extending Specification instead of IntegrationSpec. When I try to change to extend IntegrationSpec, I get the following exception when running the tests: java.lang.NullPointerException: Cannot get property 'mainContext' on null object at grails.plugin.spock.IntegrationSpec.$spock_initializeSharedFields(IntegrationSpec.groovy) – Tomas Romero Aug 16 '12 at 03:38
  • You should extend IntegrationSpec while doing an integration test https://code.google.com/p/grails-spock-examples/wiki/Overview#Integration_tests Is there a point where you declare that null mainContext? Which version of the spock plugin are you currently using? Can you add a piece of code to have a look at? – lucke84 Aug 16 '12 at 08:59
  • I'm using plugin ":spock:0.6". I never declare mainContext as a variable. I've updated the question with my test code – Tomas Romero Aug 17 '12 at 01:16
  • I think your mixing up unit tests and integration tests. An integration test is not meant to test a domain class (with the testfro annotation), but a service or a bunch of utils (like named queries). Anyway, I'm going to edit my answer trying to use the code you added to the question. – lucke84 Aug 17 '12 at 08:46
  • Later I will upload a controllerSpec code that is giving me the same problem. Should I use unit tests here to? – Tomas Romero Aug 17 '12 at 16:22
  • Based on the code you posted, I was ablt to correct my controller spec. The error I was having was that I was using @TestFor(JugadorControllerSpec) – Tomas Romero Aug 18 '12 at 03:38
  • Glad this was useful for you :) – lucke84 Aug 18 '12 at 21:06
1

Accepted answer above is good for unit tests of controllers that need service classes injected.

If you defined other spring managed beans in the resources.groovy and need them injected you can add this line at the top of your spec class

static loadExternalBeans = true //<-- loads resources.groovy beans

Source: http://grails.github.io/grails-doc/2.4.4/guide/testing.html#unitTesting

Adding static loadExternalBeans = true field definition to a unit test class makes the Grails unit test runtime load all bean definitions from grails-app/conf/spring/resources.groovy and grails-app/conf/spring/resources.xml files.

dbrin
  • 15,525
  • 4
  • 56
  • 83