Migration from JUnit 4 to JUnit 5
Introduction
Do I have to migrate all tests?
- like in the transition from version three to four JUnit 4 and JUnit 5 tests can co-exist, in general there is no need to migrate all tests immediately
JUnit 4 to 5 migration recipes
Replace @Test
imports
import org.junit.Test;
becomesimport org.junit.jupiter.api.Test;
Replace @Before
with @BeforeEach
Replace @After
with @AfterEach
Replace @BeforeClass
with @BeforeAll
Replace @AfterClass
with @AfterAll
Replace HierarchicalContextRunner
with @Nested
- instead of
@RunWith(HierarchicalContextRunner.class)
on the top-level class, annotate all@Nested
classes
Use @DisplayName("...")
- annotate top-level test classes,
@Nested
test classes and@Test
methods via@DisplayName("...")
to better describe tested behaviour (you may like to form sentences along the nesting)
Migrate @Test(expected = Throwable.class)
- new
@Test
annotation no longer carries expected exception, instead useassertThrows(...)
:
@Test
void simpleExceptionTesting() {
assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
}
or
@Test
void advancedExceptionTesting() {
final Throwable exception =
assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
- or in BDD style use catch-exception like this:
import static com.googlecode.catchexception.apis.BDDCatchException.thenThrown;
import static com.googlecode.catchexception.apis.BDDCatchException.when;
class MyTest {
@Test
void catchExceptionTesting() {
// given
// ...
when(() -> {
throw new IllegalArgumentException("a message");
});
thenThrown(IllegalArgumentException.class);
}
}
which requires this dependency in your pom.xml:
<dependency>
<groupId>eu.codearte.catch-exception</groupId>
<artifactId>catch-exception</artifactId>
<version>2.0.0-beta-1</version>
<scope>test</scope>
</dependency>
Mockito migration recipes
Replace usage of MockitoJUnitRunner
with @ExtendWith(MockitoExtension.class)
- add this dependency to your pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class MyTest { ... }
Snippets
How to assert exception message
import static com.googlecode.catchexception.apis.BDDCatchException.caughtException;
import static com.googlecode.catchexception.apis.BDDCatchException.when;
import static org.assertj.core.api.BDDAssertions.then;
@DisplayName("UserBuilder")
class UserBuilderTest {
@Test
@DisplayName("should raise IllegalArgumentException on missing username.")
void shouldRaiseExceptionOnMissingUsername() {
// given
final UserBuilder userBuilder = new UserBuilder();
when(() -> userBuilder.build());
then(caughtException())
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("username");
}
}
- required Maven dependencies in pom.xml:
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>eu.codearte.catch-exception</groupId>
<artifactId>catch-exception</artifactId>
<version>2.0.0-beta-1</version>
<scope>test</scope>
</dependency>
Additional material
Contribute
Feel free to fork this project, send me pull requests, and issues through the project’s GitHub page.