Thursday, September 8, 2011

Spock in a Gradle-Powered Groovy Project

Spock. Is. Great.
One can do wonderful things with Spock, at leat when it comes to testing software. One of the fun things is that one can use Spock both for Groovy and for Java and obviously for mixed projects as well. I'll write about usecases and examples in another post. This one is about setting up Spock for a Gradle-powered Groovy project.

Basic Build

Spock relies heavily on Groovy itself, so the desired Spock version has to match the Groovy dependency for the project.
I tried it with Groovy-1.8.1 and Spock-0.5-groovy-1.8.
Excerpt from the build.gradle file:
apply plugin: 'groovy'
apply plugin: 'eclipse'

repositories { 
  mavenCentral()
} 

dependencies {
  groovy 'org.codehaus.groovy:groovy-all:1.8.1'
  testCompile 'org.spockframework:spock-core:0.5-groovy-1.8'
}
However, the gradle eclipse fails with an unresolved dependency:
:eclipseClasspath
:: problems summary ::
:::: WARNINGS
		module not found: org.codehaus.groovy#groovy-all;1.8.0-beta-3-SNAPSHOT
[...]
FAILURE: Build failed with an exception.

* Where:
Build file '/home/thevis/spock-test/build.gradle'

* What went wrong:
Execution failed for task ':eclipseClasspath'.
Cause: Could not resolve all dependencies for configuration 'detachedConfiguration1':
    - unresolved dependency: org.codehaus.groovy#groovy-all;1.8.0-beta-3-SNAPSHOT: not found


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 1.431 secs
What does this mean? gradle dependencies does not show any peculiarities. So I really don't know.
Fortunately, although kind of annoying, this is not really a problem for the project. Since the project is a Groovy project already, it is possible to exclude all the transitive Groovy dependency stuff introduced by Spock. One possibility is to change the Spock dependency in the build file to:
  testCompile ('org.spockframework:spock-core:0.5-groovy-1.8') {
    transitive = false
  }
Alternatively, one could also exclude just the single missing dependency explicitely:
  testCompile ('org.spockframework:spock-core:0.5-groovy-1.8') {
    exclude 'org.codehaus.groovy:groovy-all:1.8.0-beta-3-SNAPSHOT'
  }
Either way gradle eclipse will succeed.

Adding Optional Features

If you want to make use of Spock's mocking and stubbing support (and I'm sure you want) the basic configuration from above is kind of limited, since it allows only mocking of interfaces. Spock lets you also mock and stub classes and even bypass the standard object construction. For these purposes, Spock depends both on cglib-nodep and objenesis, but declares these dependencies as optional. Thus, we have to declare them ourselves:
  testCompile 'cglib:cglib-nodep:2.2'
  testCompile 'org.objenesis:objenesis:1.2'

Complete Build File

Finally, here is the build.gradle in its full glory providing full mock and stub support with Spock: Alternatively, one could also exclude just the single missing dependency explicitely:
apply plugin: 'groovy'
apply plugin: 'eclipse'

version = '0.1.0-SNAPSHOT'
sourceCompatibility = '1.6'

repositories { 
  mavenCentral()
} 

dependencies {
  groovy 'org.codehaus.groovy:groovy-all:1.8.1'

  testCompile ('org.spockframework:spock-core:0.5-groovy-1.8') {
    transitive = false
  }
  testCompile 'cglib:cglib-nodep:2.2'
  testCompile 'org.objenesis:objenesis:1.2'
  testCompile 'junit:junit:4.7'
}
Happy specifying!

No comments:

Post a Comment