Chapter 2 of 18
02 — Integers
assertEquals on primitives and parameterized tests with @CsvSource.
Kata: Adder.add(a, b) returns the sum of two integers.
New ideas: assertEquals on primitives, parameterized tests — one test method, many cases.
Step 1 — write the test
package integers;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AdderTest {
@Test
void addsTwoIntegers() {
assertEquals(4, Adder.add(2, 2));
}
}
Run it: RED — Adder doesn’t exist, compilation fails.
Step 2 — minimum code, then grow
public static int add(int a, int b) {
return a + b; // one line, honest
}
GREEN.
Step 3 — one test isn’t enough: parameterize it
One test with one input is shallow. The JUnit 5 idiom for “many inputs, one contract” is a parameterized test:
@ParameterizedTest(name = "{0} + {1} = {2}")
@CsvSource({
"1, 2, 3",
"2, 2, 4",
"0, 5, 5",
"-3, 3, 0"
})
void addsPairsOfIntegers(int a, int b, int expected) {
assertEquals(expected, Adder.add(a, b));
}
@CsvSource gives you one row per input — the CSV table is your test data. The name
attribute makes every case read like a sentence in the test report: 2 + 2 = 4.
Java-specific notes
assertEqualsworks on primitives directly;intvslongare different types, so JUnit offers overloads for each — the compiler will make you be explicit.- Order matters:
assertEquals(**expected**, **actual**). Get it backwards and the failure message lies to you. intarithmetic doesn’t overflow-check.Integer.MAX_VALUE + 1silently wraps. For values where that matters (money, ids) you’d reach forBigDecimalorlong— but that’s a question about types, not about tests.
Run it
gradle test --tests "integers.AdderTest"
Key takeaway: one test teaches you assertEquals; a parameterized test teaches you value.
A row per {input, expected} case turns one test method into a table of cases.
Next: 03 — iteration, where the test drives a for loop into existence.