Groovy Guide — Testing: Unit Testing with JUnit and Groovy
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