Java + Spring Boot track

Lesson 22 · Part 5: Modern Java

JUnit Testing

To say that code "works" it needs to be verified. JUnit 5 is Java's de facto standard testing framework, providing a short and clear annotation-based API

Part 5: Modern Java3 min readFree lesson

To say that code "works" it needs to be verified. JUnit 5 is Java's de facto standard testing framework, providing a short and clear annotation-based API.

Learning Objectives

  • Know the location of src/test/java in the Maven project
  • Use @Test, @BeforeEach, @AfterEach, @DisplayName
  • Know the difference between assertEquals / assertTrue / assertThrows
  • Run the test with mvn test

Key concepts

1) Maven dependencies

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.5</version>
    <scope>test</scope>
</dependency>

scope=test is not included in the operating code.

2) Basic testing

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    @Test
void add returns the sum of two numbers () {
        assertEquals(5, new Calculator().add(2, 3));
    }
}

3) Life cycle

@BeforeEach void setUp() { ... }    //Run before each @Test
@AfterEach  void tearDown() { ... } //Run after each @Test
@BeforeAll  static void all() { ... }  //Once at the start of the entire class
@AfterAll   static void clean() { ... } //Once at the end of the entire class

4) Exception testing

@Test
void zero_division() {
    assertThrows(ArithmeticException.class,
        () -> new Calculator().divide(10, 0));
}

5) mvn test

cd 22_JUnit_test
mvn test

JUnit 5 automatically discovers and executes it and outputs the results.

See as example

Example 1 — Calculator.java: Operational code

package com.codingnow.lecture.modern22;

public class Calculator {
    public int add(int a, int b) { return a + b; }
    public int subtract(int a, int b) { return a - b; }
    public int divide(int a, int b) {
        if (b == 0) throw new ArithmeticException("/ zero");
        return a / b;
    }
}

Example 2 — CalculatorTest.java: The most basic test

package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    Calculator calc = new Calculator();

    @Test
    @DisplayName("add returns the sum of two numbers")
void add returns_sum() {
        assertEquals(5, calc.add(2, 3));
        assertEquals(0, calc.add(-1, 1));
    }

    @Test
    void divide_by_zero() {
        assertThrows(ArithmeticException.class, () -> calc.divide(10, 0));
    }
}

mvn test execution results (partial)

[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

Example 3 — FixtureTest.java: Lifecycle

package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class FixtureTest {
    Calculator calc;

    @BeforeEach
    void setUp() {
        calc = new Calculator();
        System.out.println("(setUp)");
    }

    @AfterEach
    void tearDown() {
        System.out.println("(tearDown)");
    }

    @Test
    void test_add() { assertEquals(7, calc.add(3, 4)); }

    @Test
    void test_sub() { assertEquals(1, calc.subtract(4, 3)); }
}

(setUp) and (tearDown) are displayed on the console for each test.

Example 4 — AssertionsTest.java: Various assertions

package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

class AssertionsTest {
    @Test
    void variety() {
        assertTrue(2 + 2 == 4);
        assertFalse("hi".isEmpty());
        assertNotNull("");
        assertNull(null);
        assertArrayEquals(new int[]{1, 2, 3}, new int[]{1, 2, 3});
        assertIterableEquals(List.of("a"), List.of("a"));
    }
}

Common Mistakes

  1. Add JUnit dependency to compile scope → operation jar becomes bloated
  2. Write the @Test method only as public (in 5, both package-private or public are OK, only private is not OK)
  3. Dependency between tests (results of one test affect other tests)
  4. Change the argument order like assertEquals(actual, expected) (correct answer first)
  5. Satisfaction by directly catching exceptions with try/catch → Use assertThrows

Cleanup

  • Start automated verification with JUnit 5 + Maven
  • The @Test method is small and only verifies one thing.
  • Separate common initialization with @BeforeEach
  • Verification of exception flow diagram with assertThrows

Try it yourself

cd 05_Modern_Java/22_JUnit_Test
mvn test

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/main/java/com/codingnow/lecture/modern22/Calculator.javaJava
package com.codingnow.lecture.modern22;

/** Simple calculator.*/
public class Calculator {
    public int add(int a, int b) { return a + b; }
    public int subtract(int a, int b) { return a - b; }
    public int divide(int a, int b) {
        if (b == 0) throw new ArithmeticException("/ zero");
        return a / b;
    }
}
src/test/java/com/codingnow/lecture/modern22/AssertionsTest.javaJava
package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertIterableEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

class AssertionsTest {
    @Test
    void variety() {
        assertTrue(2 + 2 == 4);
        assertFalse("hi".isEmpty());
        assertNotNull("");
        assertNull(null);
        assertArrayEquals(new int[]{1, 2, 3}, new int[]{1, 2, 3});
        assertIterableEquals(List.of("a"), List.of("a"));
    }
}
src/test/java/com/codingnow/lecture/modern22/CalculatorTest.javaJava
package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class CalculatorTest {
    Calculator calc = new Calculator();

    @Test
    @DisplayName("add returns the sum of two numbers")
void add returns_sum() {
        assertEquals(5, calc.add(2, 3));
        assertEquals(0, calc.add(-1, 1));
    }

    @Test
void subtract_normal() {
        assertEquals(2, calc.subtract(5, 3));
    }

    @Test
    void divide_by_zero() {
        assertThrows(ArithmeticException.class, () -> calc.divide(10, 0));
    }
}
src/test/java/com/codingnow/lecture/modern22/FixtureTest.javaJava
package com.codingnow.lecture.modern22;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class FixtureTest {
    Calculator calc;

    @BeforeEach
    void setUp() {
        calc = new Calculator();
        System.out.println("(setUp)");
    }

    @AfterEach
    void tearDown() {
        System.out.println("(tearDown)");
    }

    @Test
    void test_add() { assertEquals(7, calc.add(3, 4)); }

    @Test
    void test_sub() { assertEquals(1, calc.subtract(4, 3)); }
}

Assignment

Problem — StringUtils Verification

  • Reference solution: Maven project shown below.
  • Core concepts: TDD, assertEquals, assertTrue

Requirements

  • StringUtils.reverse(String) — Flip string
  • StringUtils.isPalindrome(String) — Palindrome status (ignoring case, ignoring spaces)
  • Write Normal/Edge case tests for each of the above two methods.

Expected behavior

  • Passed all tests when running mvn test.

Hint

  • StringUtils is src/main/java/.../StringUtils.java
  • The test is src/test/java/.../StringUtilsTest.java

Check the correct answer

Compare it with the reference solution below.

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

pom.xmlXML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.codingnow</groupId>
    <artifactId>lecture-modern22-hw</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.10.5</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.5</version>
            </plugin>
        </plugins>
    </build>
</project>
src/main/java/com/codingnow/lecture/modern22hw/StringUtils.javaJava
package com.codingnow.lecture.modern22hw;

/** String utility.*/
public class StringUtils {
    /** Reverses the string and returns it.*/
    public static String reverse(String s) {
        if (s == null) return null;
        return new StringBuilder(s).reverse().toString();
    }

    /** Palindrome status (ignoring case, ignoring spaces).*/
    public static boolean isPalindrome(String s) {
        if (s == null) return false;
        String t = s.replace(" ", "").toLowerCase();
        return t.equals(reverse(t));
    }
}
src/test/java/com/codingnow/lecture/modern22hw/StringUtilsTest.javaJava
package com.codingnow.lecture.modern22hw;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

class StringUtilsTest {

    @Test
void reverse_normal() {
        assertEquals("avaJ", StringUtils.reverse("Java"));
    }

    @Test
void reverse_empty string() {
        assertEquals("", StringUtils.reverse(""));
    }

    @Test
void reverse_null_is_null() {
        assertNull(StringUtils.reverse(null));
    }

    @Test
void palindrome_word() {
        assertTrue(StringUtils.isPalindrome("level"));
    }

    @Test
void palindrome_space_ignore_case() {
        assertTrue(StringUtils.isPalindrome("A man a plan a canal Panama"));
    }

    @Test
void palindrome_not_if() {
        assertFalse(StringUtils.isPalindrome("Hello"));
    }
}

Learn this lesson with a mentor

Work through the Java + Spring Boot track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now