By far the most popular java library

Last major release in 2006

JUnit 4 Limitations

  1. Difficult to evolve
    • One Jar used by:
      • Developers
      • Build tools + IDEs (maven/gradle +intellij/eclipse)
  2. No lambda support
  3. Difficult to extend

JUnit 5 Origins

  • Started by a group of test enthusiasts + JUnit 4 maintainers
  • Originally called JUnit Lambda
  • Crowdfunded project in 2015
  • €53,937 raised by 474 backers
  • Completely rewritten (but backward compatible)
  • Released October 2017

JUnit 5 in a nutshell

  1. New modular architecture
  2. Forward and backward compatible
  3. New Extension model
    • Rules and Runners replaced with Extensions
    • Dependency Injection support
  4. New features
    1. Lambda support
    2. Nested tests
    3. Dynamic tests
    4. Classes & Tests can be package protected
    5. Some renaming

New Modular Architecture!

New Modular Architecture

  • Separating concerns
    1. An API for writing tests
    2. An engine to discover and run tests
      • An engine to discover and run a specific type of test (JUnit 4, JUnit5, Cucumber...)
      • A platform to run this engine and report results
      • A engine API in between them

Three projects evolved

    1. JUnit Jupiter
      • New Test API and Engine Implementation
    2. JUnit Vintage
      • Engine Implementation for JUnit 4
    3. JUnit Platform
      • Engine API and Platform API for build tools/IDEs

New Extension Model!

Rules and Runners replaced with Extensions

JUnit 4 Extension Model​

@RunWith(Parameterized.class)
@RunWith(Cucumber.class)
@RunWith(PowerMockRunner.class)
  1. Test Runners
    • The only way to extend JUnit until 4.7
    • Very Powerful
    • Heavyweight
    • Could only have one runner on a class

JUnit 4 Extension Model​

@Rule
public ExpectedException exception = ExpectedException.none();

@ClassRule
public static final KafkaJunitRule KAFKA_RULE = new KafkaJunitRule();
  1. Test Rules in JUnit 4.7
    • Big improvement
    • Generally limited to running some code before and after a test

JUnit 5 Extensions​

@ExtendWith(KafkaJunitExtension.class, MockitoExtension.class)
class KafkaIntegrationTest {

Extend your test class with the @ExtendWith annotation

JUnit 5 Extensions​

public class KafkaJunitExtension implements BeforeAllCallback, AfterEachCallback, 
                                            BeforeEachCallback, AfterAllCallback,
                                            ParameterResolver
  • Extensions can Implement as many extension points as needed

Extension Points

BeforeAllCallback

    BeforeEachCallback

        BeforeTestExecutionCallback

        AfterTestExecutionCallback

    AfterEachCallback

AfterAllCallback

Lifecycle Extension points

TestExecutionExceptionHandler

ExecutionCondition
ParameterResolver

TestInstancePostProcessor

Dependency Injection Extension points

Parameter Injection

Extensions can inject parameters into:

  1. Constructors
  2. SetUp/TearDown methods
  3. Test methods
@Test
@DisplayName("messages should be transformed and republished to Kafka")
void transform_and_republish_to_kafka(EphemeralKafkaBroker broker) {
    broker.getKafkaPort()
    ...
}

New Features!

Lambda support

Assertions.assertAll(() -> assertThat(msg).isNotNull(),
                     () -> assertThat(msg.key()).isEqualTo("keyA"),
                     () -> assertThat(msg.value()).isEqualTo("valueA"))
assertThrows(IllegalArgumentException.class, () -> viewMetadata.setTopN(-1))
assertFalse(testConditionIsTrue(), () -> "Really " + "expensive " + "message" + ".");

Test Interfaces

public interface ComparableContract<T extends Comparable<T>> extends Testable<T> {

    T createSmallerValue();

    @Test
    default void returnsZeroWhenComparedToItself() {
        T value = createValue();
        assertEquals(0, value.compareTo(value));
    }

    @Test
    default void returnsPositiveNumberComparedToSmallerValue() {
        T value = createValue();
        T smallerValue = createSmallerValue();
        assertTrue(value.compareTo(smallerValue) > 0);
    }

    @Test
    default void returnsNegativeNumberComparedToSmallerValue() {
        T value = createValue();
        T smallerValue = createSmallerValue();
        assertTrue(smallerValue.compareTo(value) < 0);
    }

}

Nested Test Classes

Demo

Migration

  • Started with our smallest repository
  • What dependencies do I need?
    • No longer just one jar
  • What to do about Rules and Runners?
    • Backward compatible but ideally convert to extensions

Questions?

Made with Slides.com