Skip to content
Spock Testing Patterns
step 1/5

Reading — step 1 of 5

Learn

~2 min readSpock, Gradle, Modern Groovy

Spock is the Groovy testing framework. Built on JUnit but using Groovy DSL — concise, expressive, and uniquely good at parameterized tests.

A Spock test is a class extending spock.lang.Specification:

import spock.lang.Specification

class MathSpec extends Specification {
    def "adding two numbers gives the sum"() {
        expect:
            1 + 2 == 3
    }

    def "subtraction works in reverse"() {
        when:
            def result = 10 - 3

        then:
            result == 7
    }
}

Key idioms:

  • Test name is a string, not a method name. Reads like English in test reports.
  • given: / when: / then: / expect: are Spock's BDD-style blocks.
  • then: block: assertions are bare expressions. No assertEquals.

given / when / then

  • given: — setup
  • when: — action under test
  • then: — assertions on the result
  • expect: — for tests with no preceding action (combines when+then)
  • cleanup: — always runs (like finally)
def "divide two numbers"() {
    given:
        def calc = new Calculator()

    when:
        def result = calc.divide(10, 2)

    then:
        result == 5
}

Exceptions

def "divide by zero throws"() {
    when:
        new Calculator().divide(10, 0)

    then:
        ArithmeticException e = thrown()
        e.message.contains("zero")
}

thrown() is a Spock magic that asserts an exception was thrown.

Data-driven tests

The killer feature. Where: clause runs the test once per data row:

def "max of two numbers"() {
    expect:
        Math.max(a, b) == max

    where:
        a   | b   || max
        1   | 2   || 2
        5   | 3   || 5
        7   | 7   || 7
        -1  | -5  || -1
}

Four test runs from one method. The pipe-table is a Groovy DSL — two pipes (||) separate inputs from expected outputs (convention).

Mocking

def "calls dependency"() {
    given:
        def db = Mock(Database)
        def service = new UserService(db)

    when:
        service.findUser(42)

    then:
        1 * db.lookup(42) >> { id -> [name: "Ada"] }
}
  • Mock(Type) creates a mock
  • 1 * db.lookup(42) asserts the call happened exactly once
  • >> { ... } provides the response

Spock's 1 * syntax replaces verbose verify(db, times(1)).lookup(42) from Mockito.

Why Spock

  • Groovy + JUnit ergonomics that Java tests can't match
  • Data-driven tables read like documentation
  • Built-in mocking (no Mockito setup)
  • Cleaner than JUnit5 + AssertJ + Mockito for many cases

Most JVM shops adopting Groovy use Spock for tests. Even pure-Java projects often have Groovy/Spock for tests because of this.

Caveats

  • Smaller community than JUnit
  • Breaking changes in Spock 2.x (uses JUnit 5 platform)
  • IDE support varies (best in IntelliJ)
  • Adds Groovy as a build dependency for tests

For Judge0 (single-file scripts), Spock isn't available. The patterns shown are how it works in real Gradle projects.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…