Common updates from JUnit 4 to JUnit 5 - neighbourhoodie/logging-log4j2 GitHub Wiki
https://www.baeldung.com/junit-5-migration
junit4
@Test(expected = UnsupportedOperationException.class)
public void ...() {
convertToEntity();
}
turns to
import static org.junit.jupiter.api.Assertions.assertThrows;
@Test
public void testConvertToEntityAttribute() {
assertThrows(UnsupportedOperationException.class, () -> this.converter.convertToEntityAttribute(null));
}
Update the import to
org.junit.jupiter.api.Assertions
Note for any assertions with error messages, the message is moved as the second argument.
For example:
// JUnit 4
assertTrue("No messages returned", messages != null && messages.size() > 0);
// JUnit 5
assertTrue(messages != null && messages.size() > 0, "No messages returned");
Since JUnit 5 does not directly provide assertThat
, we switch to using org.hamcrest.MatcherAssert.assertThat
from the hamcrest library.
Replace org.junit.Assert.assertThat
with org.hamcrest.MatcherAssert.assertThat
Also import the Matchers:
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.emptyCollectionOf;
import static org.hamcrest.Matchers.hasItemInArray;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.theInstance;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.empty;
Remove @Category
because JUnit 5 doesn't support categories like JUnit 4. Instead, it uses tags (@Tag
), which you can adapt based on your requirements.
junit4
import org.junit.experimental.categories.Category;
@Category(Layouts.Yaml.class)
public class Test {...}
junit5
import org.junit.jupiter.api.Tag;
@Tag("Layouts.Yaml")`
public class Test {...}
Add imports:
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
Replace @RunWith(MockitoJUnitRunner.class)
with @ExtendWith(MockitoExtension.class)
- Replace
@RunWith(Parameterized.class)
with@ParameterizedTest
. Also remove@Test
as@ParameterizedTest
will cover that. - Instead of
@Parameterized.Parameters
, use@MethodSource
to supply the test parameters - Remove the constructor, as JUnit 5 passes parameters directly to the test methods
- The data() method now returns a Stream<>, which JUnit 5 uses for parameterized tests
junit4
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import com.google.common.collect.ImmutableList;
import java.util.List;
@RunWith(Parameterized.class)
@Parameterized.Parameters(name = "{0}")
public static List<String> data() throws IOException {
return ImmutableList.of("logger-config/LoggerConfig/", "logger-config/AsyncLoggerConfig/");
}
@Test
...
junit5
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
public static Stream<String> data() {
return Stream.of("logger-config/LoggerConfig/", "logger-config/AsyncLoggerConfig/");
}
@ParameterizedTest(name = "{0}")
@MethodSource("data")
@ClassRule
is deprecated in Junit5 and, unfortunately, the translation is not straight forward. It depends on the implementation.
junit4
import org.apache.logging.log4j.core.test.junit.LoggerContextRule;
...
private static final String CONFIG = "log4j2-pattern-layout-with-context.xml";
@ClassRule
public static LoggerContextRule context = new LoggerContextRule(CONFIG);
public void testfun() {
listAppender = context.getRequiredAppender("list", ListAppender.class);
listAppender.clear();
junit5
import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
import org.apache.logging.log4j.core.test.junit.Named;
@LoggerContextSource(value = "log4j2-jdbc-dbcp2.xml")
public void beforeEach(@Named("list") final ListAppender appender) {
this.listAppender = appender.clear();
})
If you need the context
in a function, you can just pass it as a param:
public void testNoUserSet(final LoggerContext context) {
final Logger logger = context.getLogger(getClass());
@Rule and @ClassRule no longer exist; superseded by @ExtendWith and @RegisterExtension.
Some of the Rules can be turned into an Extention. James helped with that for the SecurityManagerTestRule and here is the example: https://github.com/neighbourhoodie/logging-log4j2/pull/9/commits/0519c80936ef780c3bce1357565c6774888d4323 or in this PR
package org.apache.logging.log4j.test.junit;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class SecurityManagerTestRule implements TestRule {
public SecurityManagerTestRule(final SecurityManager securityManager) {
this.securityManager = securityManager;
}
private SecurityManager securityManagerBefore;
private final SecurityManager securityManager;
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
before();
try {
base.evaluate();
} finally {
after();
}
}
private void after() {
System.setSecurityManager(securityManagerBefore);
}
private void before() {
securityManagerBefore = System.getSecurityManager();
System.setSecurityManager(securityManager);
}
};
}
}
package org.apache.logging.log4j.test.junit;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
public class SecurityManagerExtension implements BeforeEachCallback, AfterEachCallback {
private SecurityManager securityManagerBefore;
private final SecurityManager securityManager;
public SecurityManagerExtension(final SecurityManager securityManager) {
this.securityManager = securityManager;
}
public void beforeEach(ExtensionContext ctx) {
securityManagerBefore = System.getSecurityManager();
System.setSecurityManager(securityManager);
}
public void afterEach(ExtensionContext ctx) {
System.setSecurityManager(securityManagerBefore);
}
}
diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilSecurityManagerTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilSecurityManagerTest.java
index beb7cc345b..bb8365a92d 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilSecurityManagerTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilSecurityManagerTest.java
@@ -20,15 +20,15 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
import java.security.Permission;
-import org.apache.logging.log4j.test.junit.SecurityManagerTestRule;
-import org.junit.Rule;
-import org.junit.Test;
+import org.apache.logging.log4j.test.junit.SecurityManagerExtension;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
+import org.junit.jupiter.api.extension.RegisterExtension;
@ResourceLock("java.lang.SecurityManager")
public class LoaderUtilSecurityManagerTest {
- @Rule
- public final SecurityManagerTestRule rule = new SecurityManagerTestRule(new TestSecurityManager());
+ @RegisterExtension
+ public final SecurityManagerExtension ext = new SecurityManagerExtension(new TestSecurityManager());
private static class TestSecurityManager extends SecurityManager {
Junit4:
public class ContextStackJsonAttributeConverterTest {
private ContextStackJsonAttributeConverter converter;
@Rule
public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
junit5
import org.apache.logging.log4j.test.junit.UsingThreadContextStack;
@UsingThreadContextStack
public class ContextStackJsonAttributeConverterTest {...}
Please update this section when they request changes for the PR we'll do in their side, to reflect the end result they are looking for.