☕
Core Java Roadmap Phase 18
0 / 40 (0%)
☰ Syllabus Index Next: P19 →

JUnit 5, Mockito & Test-Driven Development (TDD) Architecture

📂 Repository Module: Module 3_ Unit Testing with Junit 5 \ 01_Junit5_Demos & 01_TDD_Demos
📖 Textbook Alignment: Volume I — Chapter 7: Assertions, Diagnostics & Engineering Test Suites
Phase 18

JUnit 5, Mockito & Test-Driven Development (TDD) Architecture

📂 Module 3_ Unit Testing with Junit 5 \ 01_Junit5_Demos & 01_TDD_Demos
📖 Core Java Textbook Alignment: Cay S. Horstmann • Volume I — Chapter 7: Assertions, Diagnostics & Engineering Test Suites

18.1 JUnit 5 Architecture: Parameterized Tests, Nested Lifecycles & Assertions

📖 Cay S. Horstmann • Core Java Volume I — Chapter 7 ("Unit Testing and Assertions")
“Software defects must be detected automatically before software reaches production. JUnit 5 separates into three sub-projects: JUnit Platform, JUnit Jupiter (the modern programming model and extension API), and JUnit Vintage (backward compatibility for JUnit 3 and 4). With parameterized tests, developers can run identical test logic against hundreds of boundary conditions without duplicating code.”
  • AAA Pattern Arrange, Act, Assert: Every test case sets up preconditions (Arrange), invokes the target method under test (Act), and verifies expected outcomes (Assert).
  • Isolation Principle Zero Order Dependency: Tests must never depend on the execution order or shared mutable state of previous test cases.
💡 Real-World Analogy: The Crash-Test Dummy vs Real Passengers
You do not test automotive brake safety with live passengers on the highway.
Instead, you mount a calibrated Crash-Test Dummy into an isolated simulator, simulate exact collision speeds, and verify that the airbag deployed within 20 milliseconds. That is what JUnit 5 + Mockito does for backend business logic.
⚡ Pro-Tip / Interview Memory Hook: assertThrows & Mockito verify
Testing Exceptions: Never wrap test code in a manual try-catch! Use assertThrows(InvalidCredentialsException.class, () -> authService.login(null, null));.
Verification: verify(emailService, times(1)).sendWelcomeEmail(any()); proves the method was called with zero side effects on real mail servers.
📂 Module 3_ Unit Testing with Junit 5/.../EmployeeServiceTest01.java & ParameterizedTests.java
package com.accenture.ltt.junit5;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*;

public class EnterpriseTestingSuite {

    // 1. Parameterized Testing: Clean multi-input execution
    @ParameterizedTest
    @ValueSource(strings = {"radar", "level", "kayak", "rotator"})
    void shouldIdentifyPalindromes(String word) {
        String reversed = new StringBuilder(word).reverse().toString();
        assertEquals(word, reversed);
    }

    // 2. CSV Data-Driven Testing
    @ParameterizedTest
    @CsvSource({
        "100.0, 0.10, 110.0",
        "250.0, 0.20, 300.0",
        "50.0,  0.00, 50.0"
    })
    void shouldCalculateTaxCorrectly(double base, double rate, double expected) {
        double result = base + (base * rate);
        assertEquals(expected, result, 0.001);
    }

    // 3. Exception Verification
    @Test
    void shouldThrowWhenInputIsNegative() {
        assertThrows(IllegalArgumentException.class, () -> {
            if (-5 < 0) throw new IllegalArgumentException("Invalid balance");
        });
    }
}
👁 Execution & Memory Breakdown • Test Life Cycle
Step 1: JUnit 5 creates a brand-new test class instance per test method execution to enforce absolute state isolation between runs.
Step 2: @CsvSource reads comma-separated arguments and casts them directly to method parameter types via internal converters.