Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Catching up with JUnit 5

Catching up with JUnit 5

Almost 8 years have passed since the initial release of JUnit 5. But a lot has happened since then! In 12 additional feature releases the JUnit team has continually enhanced the expressiveness of the testing framework and the flexibility of the platform. This workshop is for everyone who is interested in a introduction to JUnit or who wants to catch up with the latest features and enhancements by doing hands-on exercises.

We will start with the basics, explain the lifecycle of tests and which possibilities exist for influencing it. Assertions, display names, tags, order and timeouts will be additional topics. We will then focus on parameterized tests, including custom argument sources. Last but not least, we are going to go into detail on JUnit Jupiter's extension model, introduce its core extensions, and write custom extensions together.

Avatar for Marc Philipp

Marc Philipp

May 12, 2025
Tweet

More Decks by Marc Philipp

Other Decks in Programming

Transcript

  1. Architecture JU N I T 5 P L AT F

    O R M Another Test PA R T Y T H I R D JU P I T E R VI N TAG E
  2. Display Name Generators @DisplayNameGeneration(ReplaceUnderscores.class) class A_year_is_not_supported { @Test void if_it_is_zero()

    {/*���*/} @ParameterizedTest @ValueSource(ints = { -1, -4 }) void if_it_is_negative(int year) {/*���*/} }
  3. Exercise 2: Display Names (10m) Exercise01_ListTests @DisplayName("A list") @DisplayNameGeneration(ReplaceUnderscores.class) @DisplayNameGeneration

    src/test/resources/junit- platform.properties junit.jupiter.displayname.generator.default = \ org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores
  4. Exercise 3: Tags (10m) @Tag("exercise-3") tasks.test { useJUnitPlatform { includeTags("exercise-3")

    } } <plugin> <artifactId>maven-surefire-plugin��artifactId> <version>3.5.3��version> <configuration> <groups>exercise-3��groups> ��configuration> ��plugin>
  5. Parameterized Tests • @ParameterizedTest @Test @���Source • @ValueSource @EnumSource @CsvSource

    @CsvFileSource @MethodSource @FieldSource @NullSource @EmptySource @ArgumentsSource(MyProvider.class)
  6. Extension Marker Interface • Extension • • package org.junit.jupiter.api.extension; /**

    * Marker interface for all extensions. * ��� �� public interface Extension {}
  7. Extension Point (Conditional Execution) ExecutionCondition public interface ExecutionCondition extends Extension

    { /** * Evaluate this condition for the supplied {@code ExtensionContext}. * ��� * @param context the current extension context; never {@code null} * @return the result of evaluating this condition; never {@code null} �� ConditionEvaluationResult evaluateExecutionCondition( ExtensionContext context ); }
  8. Extension Context • Extension • • public interface ExecutionCondition extends

    Extension { /** * Evaluate this condition for the supplied {@code ExtensionContext}. * ��� * @param context the current extension context; never {@code null} * @return the result of evaluating this condition; never {@code null} �� ConditionEvaluationResult evaluateExecutionCondition( ExtensionContext context ); }
  9. Extension Context Hierarchy root : ExtensionContext displayName = "JUnit Jupiter"

    parent class1 : ExtensionContext displayName = "TestClass1" parent test1 : ExtensionContext displayName = "test1()" parent test2 : ExtensionContext displayName = "test2()" parent class2 : ExtensionContext displayName = "TestClass2" parent test3 : ExtensionContext displayName = "test3()"
  10. Exercise 7: Execution Conditions (10m) ExecutionCondition @NotToday ExtensionContext.getElement() AnnotationSupport.isAnnotated() @ExtendWith(NotTodayExtension.class)

    class Exercise08_Tests { @NotToday @Test void test() { �� ��� �� } } class NotTodayExtension implements ExecutionCondition { �� ��� �� }
  11. Extension Points (Lifecycle) • BeforeAllCallback ▪ BeforeClassTemplateInvocationCallback ◦ BeforeEachCallback ◦

    BeforeTestExecutionCallback ◦ AfterTestExecutionCallback ◦ AfterEachCallback ▪ AfterClassTemplateInvocationCallback • AfterAllCallback
  12. Exercise 9 (10m): Reusable Setup ExecutorServiceExtension BeforeAllCallback AfterAllCallback TypeBasedParameterResolver<ExecutorService> Exercise09_TestsA

    B ExecutorServiceExtension ExecutorService @ExtendWith(ExecutorServiceExtension.class) class Exercise09_TestsA { @Test void test(ExecutorService executorService) { �� ��� �� } }
  13. Built-in Conditions (1/2) • @Enabled DisabledOnOs({LINUX, MAC, …}) ▪ architectures

    = "aarch64" • @Enabled DisabledOnJre({JAVA_11, …}) • @Enabled DisabledForJreRange(min = JAVA_9, max = JAVA_10)
  14. Built-in Conditions (2/2) • @Enabled DisabledIfSystemProperty(named = "someKey", matches =

    "someValue") • @Enabled DisabledIfEnvironmentVariable(named = "SOME_KEY", matches = "SOME_VALUE") • @Enabled DisabledIf("customCondition") • @Enabled DisabledInNativeImage