Running spock unit tests with Maven
Asked Answered
P

4

32

On a previous project I used the Spock testing framework to unit test my Java code. I found this really productive so I am trying to add Spock tests to my current project which uses Maven as its build tool (The previous project used Gradle). While I can get Maven to compile my Spock tests (using groovy-eclipse-compiler), I am unable to get Maven to run the tests.

I've made a simple example to demonstrate my problem with 2 files:

  • pom.xml
  • src/test/java/ASpec.groovy

Contents of pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.group</groupId>
    <artifactId>my-artifact</artifactId>
    <version>0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
            <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.0.8</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <version>0.7-groovy-2.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <compilerId>groovy-eclipse-compiler</compilerId>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-compiler</artifactId>
                        <version>2.8.0-01</version>
                    </dependency>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-batch</artifactId>
                        <version>2.1.8-01</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

Contents of ASpec.groovy:

import spock.lang.Specification

class ASpec extends Specification {

    def "Test A"(){
        // Always fail
        expect: false
    }
}

When I execute mvn clean test (or mvn clean install) I would expect my single unit test to be run and fail. While it is compiled, Maven does not run it. Does any one know how to run a Spock unit test from Maven (or if it is possible?)

(I have not put my test in a package to keep the example simple. Also I have put my groovy code in src/test/java to avoid configuring the example to pick up source files from an additional directory, again to keep the example as simple as possible.)

Pettifogging answered 7/8, 2014 at 15:9 Comment(0)
E
24

Maven Surefire finds test classes by their name. Either change the class name to ATest, or reconfigure the name pattern used by Surefire. The POM for the spock-example project demonstrates how to do the latter.

Essayistic answered 7/8, 2014 at 15:23 Comment(2)
@Peter Why **/*Spec.java works and **/*Spec.groovy does not?Cyanotype
@Cyanotype not an answer but you can use **/*Spec.classAshling
B
31

This answer is purely supplemental to @PeterNiederwieser's answer. In it he mentions that you can configure the name pattern used by Surefire. Here is an example of what worked for me:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18</version>
    <configuration>
        <includes>
            <!-- By default only files ending in 'Test' will be included, so also include support for Spock style naming convention -->
            <!-- Oddly enough for Groovy files, *Spec.groovy does not work, but *Spec.java does -->
            <include>**/*Test.java</include>
            <include>**/*Spec.java</include>
        </includes>
    </configuration>
</plugin>

Source

As I mention in the comments, I'm not sure why **/*Spec.groovy didn't work, but I'm happy to be able to use the normal Spock convention here.

Blakeslee answered 17/12, 2014 at 21:42 Comment(2)
Note that if you want to include all the tests that JUnit normally finds, you'll need to include "**/Test*.java", "**/*Test.java", and "**/*TestCase.java", per the Surefire plugin documentation.Intransigence
Raising for comment about to use **/*Spec.java even when my specification files extensions are .groovyDiarmid
E
24

Maven Surefire finds test classes by their name. Either change the class name to ATest, or reconfigure the name pattern used by Surefire. The POM for the spock-example project demonstrates how to do the latter.

Essayistic answered 7/8, 2014 at 15:23 Comment(2)
@Peter Why **/*Spec.java works and **/*Spec.groovy does not?Cyanotype
@Cyanotype not an answer but you can use **/*Spec.classAshling
M
3

I had the same requirement to add Spock to my existing java web app. I tried Peters but it did not work for me. gmavenplus-plugin somehow (no idea) replaced my guava dependency with a very old google lib and my Spring application broke complaining about a non-existent method.

After literally maybe 2 or 3 dozen attempts, I finally was able to integrate my Spock Unit tests, and Integration tests and more importantly to isolate the compilation of the Spock groovy classes from my existing Java/Junit Spring/Hibernate application.

Of course if I had gradle it would have solved the issue...but this is a legacy project and therefore I had not the choice.

Below are the plugins I added. Please note the Spock unit tests end with Spec. The Spock integration tests end with IT (but most probably should be SpecIT). I put my Spock tests under src/test/groovy.

         <plugins>
            <plugin>
                <groupId>org.codehaus.gmavenplus</groupId>
                <artifactId>gmavenplus-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <!-- Without joint compilation - no dependencies between Java and Groovy (inheritance)-->
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sources>
                        <source>
                            <directory>${project.basedir}/src/main/java/groovy</directory>
                            <includes>
                                <include>**/*.groovy</include>
                            </includes>
                        </source>
                    </sources>
                    <testSources>
                        <testSource>
                            <directory>${project.basedir}/src/test/groovy</directory>
                            <includes>
                                <include>**/*.groovy</include>
                            </includes>
                        </testSource>
                    </testSources>

                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <testSourceDirectory>src/test/groovy</testSourceDirectory>
                    <testSourceDirectory>src/test/java</testSourceDirectory>
                    <includes>
                        <include>**/*Spec.java</include>
                        <!-- Yes, .java extension -->
                        <include>**/*Test.java</include>
                        <!-- Just in case having "normal" JUnit tests -->
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.20</version>
                <configuration>
                    <useFile>false</useFile>
                    <includes>
                        <include>**/*IT.java</include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

And here are my dependencies:

        <!--Spock -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>2.4.7</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <version>1.1-groovy-2.4</version>
        </dependency>

        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-spring</artifactId>
            <version>1.1-groovy-2.4</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.groovy.modules.http-builder</groupId>
            <artifactId>http-builder</artifactId>
            <version>0.7.1</version>
        </dependency>
        <!--Spock mocking dependencies -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>3.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.objenesis</groupId>
            <artifactId>objenesis</artifactId>
            <version>2.6</version>
        </dependency>

And just to let you know, my original POM had absolutely no explicit plugins AT ALL. So I had a very simply POM for my project. So, it should work for you. It is a Java 1.7 project.

...and finally, just to give you some confidence that this is not a rubbish post, I did multiple tests in order to ensure the above worked:

  1. Just build the WAR without the tests and deploy and smoke test it locally
    mvn clean install -DskipTests -Dmaven.test.skip=true

  2. Do a test compile and see if the Groovy Unit tests get compiled as well
    mvn -X clean test-compile

  3. Do a clean install without the Integration test (i made sure it was failing for this test) and see if the Groovy unit tests are run
    mvn clean install -DskipITs

  4. Just run the integration test
    mvn failsafe:integration-test

I would have liked to include screenshots of the above as proof but it would have had to be censored...So, I sincerely hope this helps you, as I was going mental trying to get this working...Maven is a huge subject area. Good luck :=)

Manyplies answered 31/8, 2017 at 15:6 Comment(0)
B
0

A problem I encountered is incompatible dependencies.

The spock-core dependency of course pulls in a dependency on the version of groovy it needs. But it is possible that other dependencies or plugins (I think thegmaven-plus plugin in my case) pull in a different, incompatible, version of groovy.

I fixed the problem by explicitly giving a dependency on the groovy package I wanted to use.

Babul answered 25/6, 2021 at 15:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.