Skip to content
Ameen Abozaid
JNR-043

Unit testing

  • 6 Lessons
  • 3 h practice (estimate)
On this page 8 topics

Overview

Topics

  • JUnit 5
  • test lifecycle
  • parameterized tests
  • assertions

Learn first

3 h of practice (estimate)

Learning outcomes

  1. Use the JUnit Jupiter lifecycle (@BeforeEach, @AfterEach, @Nested, @DisplayName).
  2. Write parameterized tests with value, CSV, and method sources.
  3. Write expressive assertions with AssertJ, including collections and exceptions.
  4. Measure coverage and explain why coverage is not quality.

Lessons

  1. 01What a unit is
  2. 02Lifecycle and structure
  3. 03Parameterized tests
  4. 04AssertJ
  5. 05Coverage and its limits
  6. 06Demo: turning copy-pasted tests into a parameterized table

Lab and exercises

Lab

JNR-043-LAB1 · Pricing rules suite

Outcomes: 1–4 · Time: ~3 h Write parameterized tests for every discount and tax combination in Shop Core. Use @Nested groups, AssertJ assertions, and a JaCoCo report. Acceptance: one table-driven test replaces at least 10 copy-pasted ones; a planted bug is caught.

Exercises (assessment: write tests for an unseen class, graded by mutation survivors)

IDOutcomeTask
JNR-043-EX011Add @BeforeEach, @DisplayName, and two @Nested classes to a Cart test; explain how many times @BeforeEach runs.
JNR-043-EX022Turn five copy-pasted isValidEmail tests into one @ParameterizedTest with @ValueSource.
JNR-043-EX032Write a @CsvSource test for a shipping-cost rule (weight, zone, expected cost) and a @MethodSource variant with objects.
JNR-043-EX043Rewrite three JUnit assertEquals checks on a list of orders using AssertJ extracting and containsExactly.
JNR-043-EX053Assert that Cart.add(null) throws IllegalArgumentException with a message containing "product".
JNR-043-EX064Write a test with no assertions that gives 100% line coverage of a method; then add the assertion that kills a mutant.
JNR-043-EX071A test calls a private method through reflection. Explain why that is a problem and how to restructure.
Show solutions
  • EX01 @BeforeEach runs once before each test, so with N tests it runs N times (for a nested class it also runs the outer @BeforeEach first).
  • EX02 @ParameterizedTest @ValueSource(strings = {"", " ", "a@", "@b.com", "a b@c.com"}) asserting isFalse().
  • EX03 @CsvSource({"1.0,LOCAL,5.00", "5.0,LOCAL,9.00", "1.0,INTL,20.00"}); the @MethodSource method returns Stream<Arguments>.
  • EX04 assertThat(orders).extracting(Order::id).containsExactly(1L, 2L);
  • EX05 assertThatThrownBy(() -> cart.add(null)).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("product");
  • EX06 Call isAdult(18) with no assertion: line covered. Add assertThat(isAdult(18)).isTrue() and isAdult(17) false; the >= to > mutant now fails.
  • EX07 Private methods are implementation detail; test them through public behavior, or extract the logic into its own class with a public API.
  • Outcome 4 (coverage is not quality) is also covered by quiz Q09–Q10 and the lab acceptance (planted bug).

Quiz

Outcomes: O1 lifecycle · O2 parameterized · O3 AssertJ · O4 coverage.

A self-check for you: nothing is graded, saved or sent anywhere. Choose an answer, then check it. You can try again as often as you like.

  1. 1Which annotation runs before every test method?O1
  2. 2@Nested is used to:O1
  3. 3Which is the best thing to test?O1
  4. 4Which source gives several columns per row?O2
  5. 5Why use @ParameterizedTest?O2
  6. 6Which AssertJ call starts an assertion?O3
  7. 7To check that code throws, use:O3
  8. 8Which verifies list contents in exact order?O3
  9. 9A test with no assertions but full line coverage:O4
  10. 10A surviving mutant means:O4

Practical part

Seven exercises JNR-043-EX01 to EX07 plus the lab; for the assessment, write tests for an unseen class and have the mutation score checked. Pass: quiz 8/10, at least five exercises correct, and few mutation survivors.

Common mistakes

One test asserting ten things; testing private methods.

Assessment

Write tests for an unseen class; graded by mutation survivors.

Career relevance

Daily practice.

Type to search levels, phases, modules and lessons.