100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Groovy and Testing with Spock

Learn how the Spock Framework uses Groovy's syntax to write expressive, structured tests with given-when-then blocks, data tables, and built-in mocking.

Practical GroovyIntermediate10 min readJul 10, 2026
Analogies

Why Spock Leans on Groovy

Spock is a testing and specification framework that runs on the JVM but is written entirely in Groovy, using a custom AST (Abstract Syntax Tree) transformation to rewrite ordinary-looking Groovy methods into structured test blocks; a Spock Specification class extends spock.lang.Specification, and each test method (called a 'feature method') is a Groovy method whose body Spock's compiler plugin restructures around labeled blocks like given:, when:, then:, and where:.

🏏

Cricket analogy: Much like the DRS system reviews an umpire's on-field call and overlays extra analysis before confirming the decision, Spock's AST transformation reviews an ordinary-looking Groovy test method and rewrites it into structured given/when/then blocks before it runs.

Specification Structure: given-when-then

The given: block sets up test fixtures using ordinary Groovy statements, when: performs the action under test, and then: contains assertions written as plain boolean expressions — no assertEquals calls needed, since Spock's power assert renders a detailed failure diagram showing the value of every subexpression when a then: condition fails, which is one of Spock's signature Groovy-powered features.

🏏

Cricket analogy: Much like a match report breaks down 'Pre-match conditions', 'The over that mattered', and 'Result' as separate labeled sections, Spock's given:, when:, and then: blocks separate setup, action, and assertion into clearly labeled sections of a test.

Data-Driven Testing with where Blocks

The where: block turns a single feature method into a data-driven test by defining a data table with the | pipe syntax, such as a | b | result followed by rows like 1 | 2 | 3, and Spock runs the entire when/then pair once per row, substituting the column values as local variables — this relies on Groovy's operator overloading of | and its dynamic method dispatch to parse what looks like an ASCII table into iterable test data.

🏏

Cricket analogy: Much like a bowling economy-rate table lists overs, runs, and wickets as columns with a row per bowler, Spock's where: block lists variables like a | b | result as columns with a row of concrete values run once per row.

groovy
import spock.lang.Specification

class ShoppingCartSpec extends Specification {

    def "adding an item increases the total price"() {
        given:
        def cart = new ShoppingCart()

        when:
        cart.addItem(new Item(name: 'Book', price: 12.50))

        then:
        cart.total == 12.50
    }

    def "discount calculation for various totals"() {
        expect:
        applyDiscount(total) == expected

        where:
        total | expected
        50    | 45.0
        100   | 85.0
        200   | 160.0
    }

    def "checkout charges the payment gateway exactly once"() {
        given:
        def gateway = Mock(PaymentGateway)
        def cart = new ShoppingCart(gateway: gateway)
        cart.addItem(new Item(name: 'Book', price: 100))

        when:
        cart.checkout()

        then:
        1 * gateway.charge(_, 100) >> true
    }
}

Mocking and Stubbing Collaborators

Spock has built-in mocking without needing Mockito: def collaborator = Mock(PaymentGateway) creates a mock, and interactions are declared directly inside then: blocks using Groovy closures and the * cardinality operator, like 1 * collaborator.charge(_, 100) >> true, where _ is Spock's wildcard matcher, >> stubs a return value, and the whole expression reads as a Groovy DSL for 'expect this method to be called this many times with these arguments, and return this value.'

🏏

Cricket analogy: Much like a net-practice bowling machine stands in for a real bowler and can be set to deliver a fixed number of specific deliveries, Spock's Mock(PaymentGateway) stands in for a real collaborator and 1 * collaborator.charge(_, 100) >> true sets exactly what it should be called with and return.

Spock's power assert in then: blocks only rewrites plain boolean expressions — wrapping an assertion in your own if/assert logic or a custom helper method loses the detailed condition-by-condition failure diagram, so keep then: conditions as direct expressions whenever possible.

  • Spock Specifications extend spock.lang.Specification and use an AST transformation to structure feature methods into given/when/then blocks.
  • The then: block uses plain boolean expressions; Spock's power assert renders a detailed failure diagram on assertion failure.
  • The where: block turns a feature method into a data-driven test using a pipe-delimited data table.
  • Spock has built-in mocking via Mock(), with interactions declared using cardinality (1 *), wildcards (_), and stubbing (>>) inside then: blocks.
  • No external assertion or mocking library (like Mockito) is required — Spock provides both natively.
  • Power assert failure output only applies to direct boolean expressions in then:, not wrapped custom assertions.
  • Spock feature methods can use plain string method names, making test intent readable as sentences.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#GroovyStudyNotes#GroovyAndTestingWithSpock#Groovy#Testing#Spock#Leans#StudyNotes#SkillVeris#ExamPrep