sormuras.github.io

JUnit 4 vs Jupiter - a high-level concept & API comparison

JUnit 4 Jupiter
org.junit org.junit.jupiter.api
Provides JUnit core classes and annotations. JUnit Jupiter API for writing tests.

♻ Common Concepts

Basic stuff is basic. Commonly.

Entry-points

JUnit 4 Jupiter
Test Test
The Test annotation tells JUnit that the public void method to which it is attached can be run as a test case. @Test is used to signal that the annotated method is a test method.

Checks

JUnit 4 Jupiter
Assert Assertions
A set of assertion methods useful for writing tests. Assertions is a collection of utility methods that support asserting conditions in tests.

Unconditional Break-outs

JUnit 4 Jupiter
Ignore Disabled
Sometimes you want to temporarily disable a test or a group of tests. @Disabled is used to signal that the annotated test class or test method is currently disabled and should not be executed.

Conditional Test Execution

JUnit 4 Jupiter
Assume Assumptions
A set of methods useful for stating assumptions about the conditions in which a test is meaningful. Assumptions is a collection of utility methods that support conditional test execution based on assumptions.

Life-cycle Hooks

JUnit 4 Jupiter
BeforeClass BeforeAll
Sometimes several tests need to share computationally expensive setup (like logging into a database). @BeforeAll is used to signal that the annotated method should be executed before all tests in the current test class.
Before BeforeEach
When writing tests, it is common to find that several tests need similar objects created before they can run. @BeforeEach is used to signal that the annotated method should be executed before each @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, and @TestTemplate method in the current test class.
After AfterEach
If you allocate external resources in a Before method you need to release them after the test runs. @AfterEach is used to signal that the annotated method should be executed after each @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, and @TestTemplate method in the current test class.
AfterClass AfterAll
If you allocate expensive external resources in a BeforeClass method you need to release them after all the tests in the class have run. @AfterAll is used to signal that the annotated method should be executed after all tests in the current test class.

🔀 Changed Concepts

Changed, evolved, matured.

Tagging and Filtering

In contrast to the limited org.junit.experimental.categories.Category annotation and its associated runner in JUnit 4, JUnit Jupiter uses simple Strings as markers. Test classes and methods can be tagged via the @Tag annotation. Those tags can later be used to filter test discovery and execution.

For a detailed description consult the Tagging and Filtering chapter in the User-Guide.

Test Instance Lifecycle

In order to allow individual test methods to be executed in isolation and to avoid unexpected side effects due to mutable test instance state, JUnit creates a new instance of each test class before executing each test method. This “per-method” test instance lifecycle is the default behavior in JUnit Jupiter and is analogous to all previous versions of JUnit, including JUnit 4. If you would prefer that JUnit Jupiter execute all test methods on the same test instance, simply annotate your test class with @TestInstance(Lifecycle.PER_CLASS).

For a detailed description consult the Test Instance Lifecycle chapter in the User-Guide.

Extension Points

In contrast to the competing Runner, @Rule, and @ClassRule concepts in JUnit 4, the JUnit Jupiter extension model consists of a single, coherent concept: the Extension API.

For a detailed description consult the Extension Model chapter in the User-Guide.

✨ New Concepts

REVOLUTION! You might have not asked for it, but it is here.

Messages

In JUnit Jupiter you should use TestReporter where you used to print information to stdout or stderr in JUnit 4.

Gathering, Grouping, Nesting

Nested tests give the test writer more capabilities to express the relationship among several group of tests.

For a detailed description consult the Nested Tests chapter in the User-Guide.

Testlets

A new kind of test is a dynamic test which is generated at runtime by a factory method that is annotated with @TestFactory.

For a detailed description consult the Dynamic Tests chapter in the User-Guide.

Test Templates

A @TestTemplate method is not a regular test case but rather a template for test cases. As such, it is designed to be invoked multiple times depending on the number of invocation contexts returned by the registered providers. Thus, it must be used in conjunction with a registered TestTemplateInvocationContextProvider extension. Each invocation of a test template method behaves like the execution of a regular @Test method with full support for the same lifecycle callbacks and extensions.

Copied over from Test Templates

Repetitions (via Test Templates)

JUnit Jupiter provides the ability to repeat a test a specified number of times simply by annotating a method with @RepeatedTest and specifying the total number of repetitions desired.

For a detailed description consult the Repeated Tests chapter in the User-Guide.

Parameterized Tests (via Test Templates)

In JUnit 4 a limiting runner was needed from package org.junit.runners.parameterized.

In JUnit Jupiter parameterized tests are implemented as a test template extension. The API resides in its own dedicated module: org.junit.jupiter.params Be sure to include it in your test compile dependencies.

For a detailed description consult the Parameterized Tests chapter in the User-Guide.

Parallel Execution

JUnit Jupiter API for influencing parallel test execution.

For a detailed description consult the Parallel Execution chapter in the User-Guide.