Unit test Groovy2.0 with Spock : setup( )

Masa picture Masa · Jan 31, 2012 · Viewed 26.2k times · Source

I am writing unit test using Spock for groovy-2.0 , and using gradle to run. If I write following the test pass.

import spock.lang.Specification

class MyTest extends Specification {  

  def "test if myMethod returns true"() {       
    expect:
      Result == true;   
    where: 
      Result =  new DSLValidator().myMethod()

  }  
}  

myMethod() is a simple method in DSLValidator class, that simply returns true.

But if I write a setup() function and create the object in setup(), my test fails: Gradel says: FAILED: java.lang.NullPointerException: Cannot invoke method myMethod() on null object

Following is what it looks like with setup(),

import spock.lang.Specification

class MyTest extends Specification {  

  def obj

  def setup(){
   obj =  new DSLValidator()
  }

  def "test if myMethod returns true"() {       
    expect:
      Result == true;   
    where: 
      Result =  obj.myMethod()

  }  
}     

Can somebody help?

Here is the solution I got to the problem:

import spock.lang.Specification

class DSLValidatorTest extends Specification {

  def validator

  def setup() {
    validator = new DSLValidator()
  }


  def "test if DSL is valid"() { 

      expect:
        true == validator.isValid()
  }  
}

Answer

Arturo Herrero picture Arturo Herrero · Jan 31, 2012

In Spock objects stored into instance fields are not shared between feature methods. Instead, every feature method gets its own object.

If you need to share an object between feature methods, declare a @Shared field.

class MyTest extends Specification {
    @Shared obj = new DSLValidator()

    def "test if myMethod returns true"() {       
        expect:
          Result == true  
        where: 
          Result =  obj.myMethod()
    }
}

class MyTest extends Specification {
    @Shared obj

    def setupSpec() {
        obj = new DSLValidator()
    }

    def "test if myMethod returns true"() {       
        expect:
          Result == true  
        where: 
          Result =  obj.myMethod()
    }
}

There are 2 fixture methods for setting up the environment:

def setup() {}         // run before every feature method
def setupSpec() {}     // run before the first feature method

I don't understand why the second example with setupSpec() works and fails with setup() because in documentation says otherwise:

Note: The setupSpec() and cleanupSpec() methods may not reference instance fields.