This episode covers unit testing with Spock and JUnit, including mocking, data-driven tests, and behavior-driven syntax. You will also learn static type checking and linting to keep Groovy code quality high from the editor onward.

Code without tests is technical debt that silently accumulates. Episode 11 takes you into testing practices in the Groovy ecosystem, with a focus on Spock — a testing framework born for Groovy that has become the de facto standard in JVM projects.
You'll learn unit testing with Spock and JUnit, mocking, data-driven tests, behavior-driven syntax, as well as static type checking and linting to keep code quality high.
Spock uses Groovy as its test language, so tests are written in .groovy files. Spock's basic structure consists of given, when, and then blocks that separate setup, action, and verification:
import spock.lang.Specification
class KalkulatorSpec extends Specification {
def "menjumlahkan dua angka"() {
given:
def kalkulator = new Kalkulator()
when:
def hasil = kalkulator.tambah(2, 3)
then:
hasil == 5
}
}class KalkulatorSpec extends Specification makes the class a Spock test. def "menjumlahkan dua angka"() is a test method name that can be a full sentence — that's the hallmark of behavior-driven syntax.
Spock runs on top of JUnit, so tests can be executed with any build tool:
gradle testgradle test runs all tests in the project, including Spock specs and JUnit tests. The result is HTML and XML reports that can be integrated into a CI/CD pipeline — a topic we'll dive into in episode 13.
Spock's main strength is data-driven testing. A single test method can run with many data combinations through the where block:
import spock.lang.Specification
class KalkulatorSpec extends Specification {
def "penjumlahan dengan berbagai input"() {
expect:
a + b == hasil
where:
a | b || hasil
1 | 2 || 3
5 | 5 || 10
-1 | 1 || 0
}
}where: provides a data table with || separating input from expectation. a | b || hasil defines the column headers, and each following row is one test case. If a row fails, Spock reports which row is problematic.
Mocks allow a test to isolate a unit of code from external dependencies such as databases or APIs:
import spock.lang.Specification
class LayananSpec extends Specification {
def "mengambil data dari repository mock"() {
given:
def repo = Mock(Repositori)
def layanan = new Layanan(repo)
repo.cari(1) >> "data-1"
when:
def hasil = layanan.ambil(1)
then:
hasil == "data-1"
1 * repo.cari(1)
}
}Mock(Repositori) creates a fake object, and repo.cari(1) >> "data-1" configures the return value. 1 * repo.cari(1) is interaction verification — ensuring the method was called exactly once with specific arguments.
Spock distinguishes two concepts:
>>.1 *.Both can be combined in a single expression. This pattern makes Spock tests express intent clearly, something that in JUnit requires an additional library like Mockito.
Groovy is dynamic, but type checking can be enabled at compile time with @CompileStatic:
import groovy.transform.CompileStatic
@CompileStatic
class Layanan {
String sapa(String nama) {
"Halo, ${nama}!"
}
}@CompileStatic makes the Groovy compiler check types like Java. import groovy.transform.CompileStatic speeds up execution while catching type errors at compile time — the performance trade-off will be covered in episode 16.
To check style and potential bugs, use a lint tool:
npm-groovy-lint --path src/main/groovynpm-groovy-lint --path src/main/groovy runs a CodeNarc-based checker that detects code smells and style violations. Integrate linting into CI so every pull request passes automatic checks.
Episode 11 equipped you with the foundations of Groovy testing: Spock with given/when/then blocks, data-driven tests with where, mocking and interaction verification, as well as static type checking and linting for code quality.
The key takeaways:
given/when/then blocks separate setup, action, and verification.where table with many cases.Mock creates fake objects; >> configures return values.1 * method verifies the interaction count.@CompileStatic adds type safety and execution speed.In episode 12 next, we'll discuss Gradle and build automation — Groovy build scripts in build.gradle, custom tasks, plugins, dependency management, and multi-module projects.