Skip to content

Groovy Guide — Testing: Unit Testing with JUnit and Groovy

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Groovy Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

Groovy extends JUnit testing with power assertions that show expression values on failure, concise test syntax, and seamless mocking for unit and integration tests.

What You'll Learn

  • JUnit test cases in Groovy
  • Power assertions
  • Mocking and stubs
  • Testing with databases
  • Test suites and categories

Why It Matters

Groovy's power assertions and concise syntax make tests more readable and debugging faster. Durga Antivirus Pro uses Groovy for Integration Testing.

Real-World Use

Web application testing, API validation, data pipeline testing, and build verification.

flowchart LR
    A["Testing"] --> B["JUnit Tests"]
    B --> C["Power Assert"]
    C --> D["Mocking"]
    D --> E["Integration"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

JUnit Tests

import org.junit.Test
import static org.junit.Assert.*

class CalculatorTest {
    @Test
    void testAddition() {
        def result = 2 + 3
        assertEquals(5, result)
    }

    @Test
    void testWithMessage() {
        assertTrue "Expected positive", 5 > 0
    }
}

Power Assertions

import groovy.test.GroovyAssert

class PowerAssertTest extends GroovyAssert {
    @Test
    void testPowerAssert() {
        def x = 5
        def y = 3

        // On failure, shows expression values
        assert x + y == 10
        // Assertion failed:
        // x + y == 10
        // | | |  |
        // 5 3 8  false
    }
}

Mocking with Groovy

class UserService {
    def sendEmail(user) {
        // Real email sending
    }
}

class UserController {
    def userService

    def register(name, email) {
        def user = [name: name, email: email]
        userService.sendEmail(user)
        return user
    }
}

// Test with mock
class UserControllerTest {
    @Test
    void testRegistration() {
        def controller = new UserController()
        def sentUser = null

        controller.userService = [
            sendEmail: { user -> sentUser = user }
        ]

        def result = controller.register("Alice", "a@example.com")

        assert result.name == "Alice"
        assert sentUser.email == "a@example.com"
    }
}

Using ExpandoMetaClass for Mocks

class DatabaseMock {
    def findUser(id) { [id: id, name: "Mock"] }
}

class ServiceTest {
    @Test
    void testWithMock() {
        def mockDb = new DatabaseMock()
        mockDb.metaClass.findUser = { id ->
            [id: id, name: "Test User"]
        }

        assert mockDb.findUser(1).name == "Test User"
    }
}

Test Fixtures

class DatabaseTest {
    def db

    @Before
    void setUp() {
        db = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")
        db.execute("CREATE TABLE users (id INT, name VARCHAR(100))")
    }

    @After
    void tearDown() {
        db.close()
    }

    @Test
    void testInsert() {
        db.execute("INSERT INTO users VALUES (?, ?)", [1, "Alice"])
        def result = db.firstRow("SELECT * FROM users")
        assert result.name == "Alice"
    }
}

Parameterized Tests

import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import org.junit.runner.RunWith

@RunWith(Parameterized)
class MathTest {
    def a, b, expected

    MathTest(a, b, expected) {
        this.a = a; this.b = b; this.expected = expected
    }

    @Parameters
    static def data() {
        [[1, 2, 3], [-1, 1, 0], [0, 0, 0]]
    }

    @Test
    void testAdd() {
        assert a + b == expected
    }
}

Common Mistakes

1. Using == instead of assertEquals

Groovy's == calls equals(). It works in assertions but power assertions are preferred.

2. Forgetting @Test annotation

JUnit requires @Test on each test method. Missing annotation skips the test.

3. Mutable test fixtures

Shared mutable state between tests causes flaky tests. Use @Before to reset state.

4. Power assertion with too many method calls

Power assertions show intermediate values. Keep assertions focused.

5. Not testing edge cases

Test empty collections, null values, negative numbers, and boundary conditions.

Practice Questions

1. What is a power assertion? An assertion that displays the values of all sub-expressions when the assertion fails.

2. How do you create a mock in Groovy? Use closures or maps to implement interfaces: def mock = [method: { args -> ... }].

3. What does @Before do? Runs the annotated method before each test method, used for test setup.

Challenge: Write a test suite for a calculator that uses parameterized tests and power assertions.

FAQ

{{< faq question="Can I use Spock instead of JUnit?" >} Yes. Spock is a popular Groovy testing framework with built-in mocking and parameterized tests. {{< /faq >}}

{{< faq question="What is GroovyAssert?" >} A base class that adds Groovy-specific assertions (like shouldFail) on top of JUnit. {{< /faq >}}

{{< faq question="How do I mock static methods?" >} Use Groovy's metaClass: SomeClass.metaClass.static.method = { ... }. {{< /faq >}}

{{< faq question="Can I test Groovy scripts?" >} Yes. Evaluate the script in a test and verify side effects or return values. {{< /faq >}}

{{< faq question="What is shouldFail?" >} A method from GroovyAssert that asserts a specific exception is thrown: shouldFail(IOException) { riskyCode() }. {{< /faq >}}

Mini Project

Build a test suite for a user service:

class UserValidationService {
    def validate(Map user) {
        def errors = []
        if (!user.name) errors << "Name required"
        if (!user.email?.contains("@")) errors << "Valid email required"
        if (user.age < 0 || user.age > 150) errors << "Invalid age"
        return errors
    }
}

class UserValidationTest extends GroovyAssert {
    def service = new UserValidationService()

    @Test
    void testValidUser() {
        def user = [name: "Alice", email: "a@test.com", age: 30]
        assert service.validate(user).isEmpty()
    }

    @Test
    void testMissingName() {
        def user = [email: "a@test.com", age: 30]
        assert service.validate(user).contains("Name required")
    }
}

What's Next

Now that you understand testing, explore the Spock framework for specification-style testing.

Topic Description Link
Groovy Spock Spock testing framework {{< ref "16-spock" >}}
Groovy Gradle Gradle integration {{< ref "17-gradle-integration" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro