Migrate JTL tests to JUnit 5.
diff --git a/log4j-layout-template-json/pom.xml b/log4j-layout-template-json/pom.xml
index 972b4e9..3e10b05 100644
--- a/log4j-layout-template-json/pom.xml
+++ b/log4j-layout-template-json/pom.xml
@@ -186,17 +186,33 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <skip>${maven.test.skip}</skip>
-          <excludes>
-            <exclude>**/JsonTemplateLayoutConcurrentEncodeTest.java</exclude>
-            <exclude>**/JsonTemplateLayoutTest.java</exclude>
-          </excludes>
+          <!-- Disabling the default execution and only using it to provide
+               the shared settings between individual executions. -->
+          <skip>true</skip>
           <!-- Enforcing a non-UTF-8 encoding to check that the layout
                indeed handles everything in UTF-8 without implicitly
                relying on the system defaults. -->
           <argLine>-Dfile.encoding=US-ASCII</argLine>
+          <systemPropertyVariables>
+            <!-- Enable JUnit 5 parallel execution. -->
+            <junit.jupiter.execution.parallel.enabled>true</junit.jupiter.execution.parallel.enabled>
+            <junit.jupiter.execution.parallel.mode.default>concurrent</junit.jupiter.execution.parallel.mode.default>
+          </systemPropertyVariables>
         </configuration>
         <executions>
+          <execution>
+            <id>default</id>
+            <goals>
+              <goal>test</goal>
+            </goals>
+            <configuration>
+              <skip>${skipTests}</skip>
+              <excludes>
+                <exclude>**/JsonTemplateLayoutConcurrentEncodeTest.java</exclude>
+                <exclude>**/JsonTemplateLayoutTest.java</exclude>
+              </excludes>
+            </configuration>
+          </execution>
           <!-- Dummy recycler execution -->
           <execution>
             <id>recycler-dummy</id>
@@ -206,7 +222,7 @@
             <configuration>
               <skip>${skipTests}</skip>
               <systemPropertyVariables>
-                <log4j2.layout.jsonTemplate.recyclerFactory>threadLocal</log4j2.layout.jsonTemplate.recyclerFactory>
+                <log4j2.layout.jsonTemplate.recyclerFactory>dummy</log4j2.layout.jsonTemplate.recyclerFactory>
               </systemPropertyVariables>
               <includes>
                 <include>**/JsonTemplateLayoutConcurrentEncodeTest.java</include>
@@ -309,7 +325,6 @@
               </execution>
             </executions>
             <configuration>
-              <skip>${skipTests}</skip>
               <includes>
                 <include>**/*IT.java</include>
               </includes>
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
index 4be0c7f..9f806f5 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/EcsLayoutTest.java
@@ -22,7 +22,7 @@
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collection;
 import java.util.List;
@@ -30,7 +30,7 @@
 
 import static org.apache.logging.log4j.layout.template.json.LayoutComparisonHelpers.renderUsing;
 
-public class EcsLayoutTest {
+class EcsLayoutTest {
 
     private static final Configuration CONFIGURATION = new DefaultConfiguration();
 
@@ -65,13 +65,13 @@
             .build();
 
     @Test
-    public void test_lite_log_events() {
+    void test_lite_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
         test(logEvents);
     }
 
     @Test
-    public void test_full_log_events() {
+    void test_full_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
         test(logEvents);
     }
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
index 9d32cf3..7601d44 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/GelfLayoutTest.java
@@ -23,7 +23,7 @@
 import org.apache.logging.log4j.core.time.Instant;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.math.BigDecimal;
 import java.util.Collection;
@@ -32,7 +32,7 @@
 
 import static org.apache.logging.log4j.layout.template.json.LayoutComparisonHelpers.renderUsing;
 
-public class GelfLayoutTest {
+class GelfLayoutTest {
 
     private static final Configuration CONFIGURATION = new DefaultConfiguration();
 
@@ -60,13 +60,13 @@
             .build();
 
     @Test
-    public void test_lite_log_events() {
+    void test_lite_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
         test(logEvents);
     }
 
     @Test
-    public void test_full_log_events() {
+    void test_full_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
         test(logEvents);
     }
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonLayoutTest.java
index f567310..8fb2379 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonLayoutTest.java
@@ -21,7 +21,7 @@
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.jackson.json.layout.JsonLayout;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collection;
 import java.util.List;
@@ -29,7 +29,7 @@
 
 import static org.apache.logging.log4j.layout.template.json.LayoutComparisonHelpers.renderUsing;
 
-public class JsonLayoutTest {
+class JsonLayoutTest {
 
     private static final Configuration CONFIGURATION = new DefaultConfiguration();
 
@@ -45,13 +45,13 @@
             .build();
 
     @Test
-    public void test_lite_log_events() {
+    void test_lite_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createLiteLogEvents(1_000);
         test(logEvents);
     }
 
     @Test
-    public void test_full_log_events() {
+    void test_full_log_events() {
         final List<LogEvent> logEvents = LogEventFixture.createFullLogEvents(1_000);
         test(logEvents);
     }
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.java
index 0603d68..9cb32e3 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutConcurrentEncodeTest.java
@@ -21,7 +21,7 @@
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.nio.ByteBuffer;
 import java.util.List;
@@ -31,7 +31,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-public class JsonTemplateLayoutConcurrentEncodeTest {
+class JsonTemplateLayoutConcurrentEncodeTest {
 
     private static class ConcurrentAccessError extends RuntimeException {
 
@@ -118,7 +118,7 @@
     }
 
     @Test
-    public void test_concurrent_encode() {
+    void test_concurrent_encode() {
         final AtomicReference<Exception> encodeFailureRef = new AtomicReference<>(null);
         produce(encodeFailureRef);
         Assertions.assertThat(encodeFailureRef.get()).isNull();
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutGcFreeTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutGcFreeTest.java
index da6ca86..503028c 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutGcFreeTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutGcFreeTest.java
@@ -17,7 +17,7 @@
 package org.apache.logging.log4j.layout.template.json;
 
 import org.apache.logging.log4j.core.GcFreeLoggingTestUtil;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Tag;
 
 @Tag("allocation")
@@ -25,7 +25,7 @@
 public class JsonTemplateLayoutGcFreeTest {
 
     @Test
-    public void test_no_allocation_during_steady_state_logging() throws Exception {
+    void test_no_allocation_during_steady_state_logging() throws Exception {
         GcFreeLoggingTestUtil.runTest(getClass());
     }
 
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutNullEventDelimiterTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutNullEventDelimiterTest.java
index 4af1ca1..9c16871 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutNullEventDelimiterTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutNullEventDelimiterTest.java
@@ -21,7 +21,7 @@
 import org.apache.logging.log4j.Logger;
 import org.assertj.core.api.Assertions;
 import org.awaitility.Awaitility;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
@@ -64,7 +64,7 @@
             Awaitility
                     .await()
                     .atMost(Duration.ofSeconds(10))
-                    .pollDelay(Duration.ofSeconds(2))
+                    .pollDelay(Duration.ofSeconds(1))
                     .until(() -> server.getTotalReadByteCount() >= expectedBytes.length);
 
             // Verify the received log events.
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
index fddea67..a7503fc 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
@@ -49,7 +49,7 @@
 import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.util.Strings;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
@@ -80,7 +80,7 @@
 import static org.assertj.core.api.Assertions.assertThat;
 
 @SuppressWarnings("DoubleBraceInitialization")
-public class JsonTemplateLayoutTest {
+class JsonTemplateLayoutTest {
 
     private static final Configuration CONFIGURATION = new DefaultConfiguration();
 
@@ -97,7 +97,7 @@
     private static final String LOGGER_NAME = JsonTemplateLayoutTest.class.getSimpleName();
 
     @Test
-    public void test_serialized_event() throws IOException {
+    void test_serialized_event() throws IOException {
         final String lookupTestKey = "lookup_test_key";
         final String lookupTestVal =
                 String.format("lookup_test_value_%d", (int) (1000 * Math.random()));
@@ -205,7 +205,7 @@
     }
 
     @Test
-    public void test_inline_template() throws Exception {
+    void test_inline_template() throws Exception {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World");
@@ -247,7 +247,7 @@
     }
 
     @Test
-    public void test_log4j_deferred_runtime_resolver_for_MapMessage() {
+    void test_log4j_deferred_runtime_resolver_for_MapMessage() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -288,7 +288,7 @@
     }
 
     @Test
-    public void test_MapMessage_serialization() {
+    void test_MapMessage_serialization() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -324,7 +324,7 @@
     }
 
     @Test
-    public void test_MapMessage_keyed_access() {
+    void test_MapMessage_keyed_access() {
 
         // Create the event template.
         final String key = "list";
@@ -365,7 +365,7 @@
     }
 
     @Test
-    public void test_message_fallbackKey() {
+    void test_message_fallbackKey() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -414,7 +414,7 @@
     }
 
     @Test
-    public void test_property_injection() {
+    void test_property_injection() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World");
@@ -449,7 +449,7 @@
     }
 
     @Test
-    public void test_empty_root_cause() {
+    void test_empty_root_cause() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -512,7 +512,7 @@
     }
 
     @Test
-    public void test_root_cause() {
+    void test_root_cause() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -576,7 +576,7 @@
     }
 
     @Test
-    public void test_marker_name() {
+    void test_marker_name() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -615,7 +615,7 @@
     }
 
     @Test
-    public void test_lineSeparator_suffix() {
+    void test_lineSeparator_suffix() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -651,7 +651,7 @@
     }
 
     @Test
-    public void test_main_key_access() {
+    void test_main_key_access() {
 
         // Set main() arguments.
         final String kwKey = "--name";
@@ -699,7 +699,7 @@
     }
 
     @Test
-    public void test_mdc_key_access() {
+    void test_mdc_key_access() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -786,7 +786,7 @@
     }
 
     @Test
-    public void test_mdc_pattern() {
+    void test_mdc_pattern() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -874,7 +874,7 @@
     }
 
     @Test
-    public void test_mdc_flatten() {
+    void test_mdc_flatten() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -963,7 +963,7 @@
     }
 
     @Test
-    public void test_MapResolver() {
+    void test_MapResolver() {
 
         // Create the log event.
         final StringMapMessage message = new StringMapMessage().with("key1", "val1");
@@ -999,7 +999,7 @@
     }
 
     @Test
-    public void test_StringMapMessage() {
+    void test_StringMapMessage() {
 
         // Create the log event.
         final StringMapMessage message = new StringMapMessage();
@@ -1033,7 +1033,7 @@
     }
 
     @Test
-    public void test_ObjectMessage() {
+    void test_ObjectMessage() {
 
         // Create the log event.
         final int id = 0xDEADBEEF;
@@ -1071,7 +1071,7 @@
     }
 
     @Test
-    public void test_StackTraceElement_template() {
+    void test_StackTraceElement_template() {
 
         // Create the stack trace element template.
         final String classNameFieldName = "className";
@@ -1148,7 +1148,7 @@
     }
 
     @Test
-    public void test_toSerializable_toByteArray_encode_outputs() {
+    void test_toSerializable_toByteArray_encode_outputs() {
 
         // Create the layout.
         final JsonTemplateLayout layout = JsonTemplateLayout
@@ -1211,7 +1211,7 @@
     }
 
     @Test
-    public void test_maxStringLength() {
+    void test_maxStringLength() {
 
         // Create the log event.
         final int maxStringLength = 30;
@@ -1297,7 +1297,7 @@
     }
 
     @Test
-    public void test_exception_with_nonAscii_utf8_method_name() {
+    void test_exception_with_nonAscii_utf8_method_name() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -1333,7 +1333,7 @@
     }
 
     @Test
-    public void test_event_template_additional_fields() {
+    void test_event_template_additional_fields() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -1389,7 +1389,7 @@
 
     @Test
     @SuppressWarnings("FloatingPointLiteralPrecision")
-    public void test_timestamp_epoch_resolvers() {
+    void test_timestamp_epoch_resolvers() {
 
         final List<Map<String, Object>> testCases = Arrays.asList(
                 Map(
@@ -1477,7 +1477,7 @@
     }
 
     @Test
-    public void test_timestamp_pattern_resolver() {
+    void test_timestamp_pattern_resolver() {
 
         // Create log events.
         final String logEvent1FormattedInstant = "2019-01-02T09:34:11Z";
@@ -1541,7 +1541,7 @@
     }
 
     @Test
-    public void test_level_severity() {
+    void test_level_severity() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -1586,7 +1586,7 @@
     }
 
     @Test
-    public void test_exception_resolvers_against_no_exceptions() {
+    void test_exception_resolvers_against_no_exceptions() {
 
         // Create the log event.
         final SimpleMessage message = new SimpleMessage("Hello, World!");
@@ -1634,7 +1634,7 @@
     }
 
     @Test
-    public void test_StackTraceTextResolver_with_maxStringLength() {
+    void test_StackTraceTextResolver_with_maxStringLength() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -1672,7 +1672,7 @@
     }
 
     @Test
-    public void test_null_eventDelimiter() {
+    void test_null_eventDelimiter() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map("key", "val"));
@@ -1701,7 +1701,7 @@
     }
 
     @Test
-    public void test_against_SocketAppender() throws Exception {
+    void test_against_SocketAppender() throws Exception {
 
         // Craft nasty events.
         final List<LogEvent> logEvents = createNastyLogEvents();
@@ -1879,7 +1879,7 @@
     }
 
     @Test
-    public void test_PatternResolver() {
+    void test_PatternResolver() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -1915,12 +1915,12 @@
     }
 
     @Test
-    public void test_MessageParameterResolver_with_ParameterizedMessageFactory() {
+    void test_MessageParameterResolver_with_ParameterizedMessageFactory() {
         testMessageParameterResolver(ParameterizedMessageFactory.INSTANCE);
     }
 
     @Test
-    public void test_MessageParameterResolver_with_ReusableMessageFactory() {
+    void test_MessageParameterResolver_with_ReusableMessageFactory() {
         testMessageParameterResolver(ReusableMessageFactory.INSTANCE);
     }
 
@@ -1974,7 +1974,7 @@
     }
 
     @Test
-    public void test_unresolvable_nested_fields_are_skipped() {
+    void test_unresolvable_nested_fields_are_skipped() {
 
         // Create the event template.
         final String eventTemplate = writeJson(Map(
@@ -2034,7 +2034,7 @@
 
     }
 
-    private static String writeJson(final Object value) {
+    private static synchronized String writeJson(final Object value) {
         final StringBuilder stringBuilder = JSON_WRITER.getStringBuilder();
         stringBuilder.setLength(0);
         try {
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
index 7dc201e..465d899 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/LogstashIT.java
@@ -48,7 +48,9 @@
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -67,7 +69,8 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-public class LogstashIT {
+@Execution(ExecutionMode.SAME_THREAD)
+class LogstashIT {
 
     private static final StatusLogger LOGGER = StatusLogger.getLogger();
 
@@ -157,14 +160,14 @@
     }
 
     @Test
-    public void test_lite_events() throws IOException {
+    void test_lite_events() throws IOException {
         final List<LogEvent> logEvents =
                 LogEventFixture.createLiteLogEvents(LOG_EVENT_COUNT);
         testEvents(logEvents);
     }
 
     @Test
-    public void test_full_events() throws IOException {
+    void test_full_events() throws IOException {
         final List<LogEvent> logEvents =
                 LogEventFixture.createFullLogEvents(LOG_EVENT_COUNT);
         testEvents(logEvents);
@@ -227,7 +230,7 @@
     }
 
     @Test
-    public void test_newlines() throws IOException {
+    void test_newlines() throws IOException {
 
         // Create two log events containing new lines.
         final Level level = Level.DEBUG;
@@ -295,7 +298,7 @@
     }
 
     @Test
-    public void test_GelfLayout() throws IOException {
+    void test_GelfLayout() throws IOException {
 
         // Create log events.
         final List<LogEvent> logEvents =
@@ -330,7 +333,7 @@
     }
 
     @Test
-    public void test_EcsLayout() throws IOException {
+    void test_EcsLayout() throws IOException {
 
         // Create log events.
         final List<LogEvent> logEvents =
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonReaderTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonReaderTest.java
index 7c32884..aa7992e 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonReaderTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonReaderTest.java
@@ -17,7 +17,7 @@
 package org.apache.logging.log4j.layout.template.json.util;
 
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -25,16 +25,16 @@
 import java.util.Collections;
 import java.util.LinkedHashMap;
 
-public class JsonReaderTest {
+class JsonReaderTest {
 
     @Test
-    public void test_valid_null() {
+    void test_valid_null() {
         test("null", null);
         test("[null, null]", Arrays.asList(null, null));
     }
 
     @Test
-    public void test_invalid_null() {
+    void test_invalid_null() {
         for (final String json : new String[]{"nuL", "nulL", "nul1"}) {
             Assertions
                     .assertThatThrownBy(() -> JsonReader.read(json))
@@ -46,14 +46,14 @@
     }
 
     @Test
-    public void test_valid_boolean() {
+    void test_valid_boolean() {
         test("true", true);
         test("false", false);
         test("[true, false]", Arrays.asList(true, false));
     }
 
     @Test
-    public void test_invalid_boolean() {
+    void test_invalid_boolean() {
         for (final String json : new String[]{"tru", "truE", "fals", "falsE"}) {
             Assertions
                     .assertThatThrownBy(() -> JsonReader.read(json))
@@ -65,7 +65,7 @@
     }
 
     @Test
-    public void test_valid_string() {
+    void test_valid_string() {
         test("\"\"", "");
         test("\" \"", " ");
         test("\" a\"", " a");
@@ -76,7 +76,7 @@
     }
 
     @Test
-    public void test_invalid_string_start() {
+    void test_invalid_string_start() {
         final String json = "abc\"";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -86,7 +86,7 @@
     }
 
     @Test
-    public void test_invalid_string_end() {
+    void test_invalid_string_end() {
         for (final String json : new String[]{"", " ", "\r", "\t", "\"abc"}) {
             Assertions
                     .assertThatThrownBy(() -> JsonReader.read(json))
@@ -97,7 +97,7 @@
     }
 
     @Test
-    public void test_invalid_string_escape() {
+    void test_invalid_string_escape() {
         for (final String json : new String[]{"\"\\k\"", "\"\\d\""}) {
             Assertions
                     .assertThatThrownBy(() -> JsonReader.read(json))
@@ -109,7 +109,7 @@
     }
 
     @Test
-    public void test_invalid_string_concat() {
+    void test_invalid_string_concat() {
         final String json = "\"foo\"\"bar\"";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -119,7 +119,7 @@
     }
 
     @Test
-    public void test_valid_unicode_string() {
+    void test_valid_unicode_string() {
         final String json = "\"a\\u00eF4bc\"";
         Assertions
                 .assertThat(JsonReader.read(json))
@@ -128,7 +128,7 @@
     }
 
     @Test
-    public void test_invalid_unicode() {
+    void test_invalid_unicode() {
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read("\"\\u000x\""))
                 .isInstanceOf(IllegalArgumentException.class)
@@ -136,7 +136,7 @@
     }
 
     @Test
-    public void test_valid_integers() {
+    void test_valid_integers() {
         for (final String integer : new String[]{
                 "0",
                 "1",
@@ -152,7 +152,7 @@
     }
 
     @Test
-    public void test_invalid_integers() {
+    void test_invalid_integers() {
         for (final String integer : new String[]{
                 "0-",
                 "1a"}) {
@@ -167,7 +167,7 @@
     }
 
     @Test
-    public void test_valid_decimals() {
+    void test_valid_decimals() {
         for (final String decimal : new String[]{
                 "0.0",
                 "1.0",
@@ -183,7 +183,7 @@
     }
 
     @Test
-    public void test_invalid_decimals() {
+    void test_invalid_decimals() {
         for (final String decimal : new String[]{
                 "0.",
                 ".1",
@@ -201,7 +201,7 @@
     }
 
     @Test
-    public void test_valid_arrays() {
+    void test_valid_arrays() {
         for (final String json : new String[]{
                 "[]",
                 "[ ]"}) {
@@ -225,7 +225,7 @@
     }
 
     @Test
-    public void test_invalid_array_start() {
+    void test_invalid_array_start() {
         final String json = "[";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -235,7 +235,7 @@
     }
 
     @Test
-    public void test_invalid_array_end_1() {
+    void test_invalid_array_end_1() {
         final String json = "]";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -245,7 +245,7 @@
     }
 
     @Test
-    public void test_invalid_array_comma() {
+    void test_invalid_array_comma() {
         final String json = "[,";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -255,7 +255,7 @@
     }
 
     @Test
-    public void test_invalid_array_end_2() {
+    void test_invalid_array_end_2() {
         final String json = "[1,";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -265,7 +265,7 @@
     }
 
     @Test
-    public void test_invalid_array_end_3() {
+    void test_invalid_array_end_3() {
         final String json = "[1,]";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -275,13 +275,13 @@
     }
 
     @Test
-    public void test_valid_objects() {
+    void test_valid_objects() {
         test("{}", Collections.emptyMap());
         test("{\"foo\":\"bar\"}", Collections.singletonMap("foo", "bar"));
     }
 
     @Test
-    public void test_invalid_object_start() {
+    void test_invalid_object_start() {
         final String json = "{";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -291,7 +291,7 @@
     }
 
     @Test
-    public void test_invalid_object_end() {
+    void test_invalid_object_end() {
         final String json = "}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -301,7 +301,7 @@
     }
 
     @Test
-    public void test_invalid_object_colon_1() {
+    void test_invalid_object_colon_1() {
         final String json = "{\"foo\"\"bar\"}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -311,7 +311,7 @@
     }
 
     @Test
-    public void test_invalid_object_colon_2() {
+    void test_invalid_object_colon_2() {
         final String json = "{\"foo\":}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -321,7 +321,7 @@
     }
 
     @Test
-    public void test_invalid_object_token() {
+    void test_invalid_object_token() {
         final String json = "{\"foo\":\"bar}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -331,7 +331,7 @@
     }
 
     @Test
-    public void test_invalid_object_comma() {
+    void test_invalid_object_comma() {
         final String json = "{\"foo\":\"bar\",}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
@@ -341,7 +341,7 @@
     }
 
     @Test
-    public void test_invalid_object_key() {
+    void test_invalid_object_key() {
         final String json = "{\"foo\":\"bar\",]}";
         Assertions
                 .assertThatThrownBy(() -> JsonReader.read(json))
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
index def4d42..b18368e 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
@@ -26,7 +26,7 @@
 import org.apache.logging.log4j.util.Strings;
 import org.assertj.core.api.Assertions;
 import org.assertj.core.api.SoftAssertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
 import java.math.BigDecimal;
@@ -37,10 +37,11 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 @SuppressWarnings("DoubleBraceInitialization")
-public class JsonWriterTest {
+class JsonWriterTest {
 
     private static final JsonWriter WRITER = JsonWriter
             .newBuilder()
@@ -48,56 +49,73 @@
             .setTruncatedStringSuffix("~")
             .build();
 
-    @Test
-    public void test_writeValue_null_Object() {
-        expectNull(() -> WRITER.writeValue(null));
+    private static synchronized <V> V withLockedWriterReturning(
+            final Function<JsonWriter, V> consumer) {
+        synchronized (WRITER) {
+            return consumer.apply(WRITER);
+        }
+    }
+
+    private static synchronized void withLockedWriter(
+            final Consumer<JsonWriter> consumer) {
+        synchronized (WRITER) {
+            consumer.accept(WRITER);
+        }
     }
 
     @Test
-    public void test_writeValue() {
+    void test_writeValue_null_Object() {
+        expectNull(writer -> writer.writeValue(null));
+    }
+
+    @Test
+    void test_writeValue() {
         final Object value = Collections.singletonMap("a", "b");
         final String expectedJson = "{'a':'b'}".replace('\'', '"');
-        final String actualJson = WRITER.use(() -> WRITER.writeValue(value));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeValue(value)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeObject_null_StringMap() {
-        expectNull(() -> WRITER.writeObject((StringMap) null));
+    void test_writeObject_null_StringMap() {
+        expectNull(writer -> writer.writeObject((StringMap) null));
     }
 
     @Test
-    public void test_writeObject_StringMap() {
+    void test_writeObject_StringMap() {
         final StringMap map = new JdkMapAdapterStringMap(Collections.singletonMap("a", "b"));
         final String expectedJson = "{'a':'b'}".replace('\'', '"');
-        final String actualJson = WRITER.use(() -> WRITER.writeObject(map));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeObject(map)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeObject_null_IndexedReadOnlyStringMap() {
-        expectNull(() -> WRITER.writeObject((IndexedReadOnlyStringMap) null));
+    void test_writeObject_null_IndexedReadOnlyStringMap() {
+        expectNull(writer -> writer.writeObject((IndexedReadOnlyStringMap) null));
     }
 
     @Test
-    public void test_writeObject_IndexedReadOnlyStringMap() {
+    void test_writeObject_IndexedReadOnlyStringMap() {
         final IndexedReadOnlyStringMap map =
                 new SortedArrayStringMap(new LinkedHashMap<String, Object>() {{
                     put("buzz", 1.2D);
                     put("foo", "bar");
                 }});
         final String expectedJson = "{'buzz':1.2,'foo':'bar'}".replace('\'', '"');
-        final String actualJson = WRITER.use(() -> WRITER.writeObject(map));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeObject(map)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeObject_null_Map() {
-        expectNull(() -> WRITER.writeObject((Map<String, Object>) null));
+    void test_writeObject_null_Map() {
+        expectNull(writer -> writer.writeObject((Map<String, Object>) null));
     }
 
     @Test
-    public void test_writeObject_Map() {
+    void test_writeObject_Map() {
         final Map<String, Object> map = new LinkedHashMap<String, Object>() {{
             put("key1", "val1");
             put("key2", Collections.singletonMap("key2.1", "val2.1"));
@@ -166,331 +184,358 @@
                 "'key6':[{'buzz':1.2,'foo':'bar'},{'a':'b'}]," +
                 "'key7':'7.7777777777777'" +
                 "}").replace('\'', '"');
-        final String actualJson = WRITER.use(() -> WRITER.writeObject(map));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeObject(map)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_List() {
-        expectNull(() -> WRITER.writeArray((List<Object>) null));
+    void test_writeArray_null_List() {
+        expectNull(writer -> writer.writeArray((List<Object>) null));
     }
 
     @Test
-    public void test_writeArray_List() {
+    void test_writeArray_List() {
         final List<Object> items = Arrays.asList(
                 1, 2, 3,
                 "yo",
                 Collections.singletonMap("foo", "bar"));
         final String expectedJson = "[1,2,3,\"yo\",{\"foo\":\"bar\"}]";
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_Collection() {
-        expectNull(() -> WRITER.writeArray((Collection<Object>) null));
+    void test_writeArray_null_Collection() {
+        expectNull(writer -> writer.writeArray((Collection<Object>) null));
     }
 
     @Test
-    public void test_writeArray_Collection() {
+    void test_writeArray_Collection() {
         final Collection<Object> items = Arrays.asList(
                 1, 2, 3,
                 Collections.singletonMap("foo", "bar"));
         final String expectedJson = "[1,2,3,{\"foo\":\"bar\"}]";
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_char() {
-        expectNull(() -> WRITER.writeArray((char[]) null));
+    void test_writeArray_null_char() {
+        expectNull(writer -> writer.writeArray((char[]) null));
     }
 
     @Test
-    public void test_writeArray_char() {
+    void test_writeArray_char() {
         final char[] items = {'\u0000', 'a', 'b', 'c', '\u007f'};
         final String expectedJson = "[\"\\u0000\",\"a\",\"b\",\"c\",\"\u007F\"]";
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_boolean() {
-        expectNull(() -> WRITER.writeArray((boolean[]) null));
+    void test_writeArray_null_boolean() {
+        expectNull(writer -> writer.writeArray((boolean[]) null));
     }
 
     @Test
-    public void test_writeArray_boolean() {
+    void test_writeArray_boolean() {
         final boolean[] items = {true, false};
         final String expectedJson = "[true,false]";
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_byte() {
-        expectNull(() -> WRITER.writeArray((byte[]) null));
+    void test_writeArray_null_byte() {
+        expectNull(writer -> writer.writeArray((byte[]) null));
     }
 
     @Test
-    public void test_writeArray_byte() {
+    void test_writeArray_byte() {
         final byte[] items = {Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_short() {
-        expectNull(() -> WRITER.writeArray((short[]) null));
+    void test_writeArray_null_short() {
+        expectNull(writer -> writer.writeArray((short[]) null));
     }
 
     @Test
-    public void test_writeArray_short() {
+    void test_writeArray_short() {
         final short[] items = {Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_int() {
-        expectNull(() -> WRITER.writeArray((int[]) null));
+    void test_writeArray_null_int() {
+        expectNull(writer -> writer.writeArray((int[]) null));
     }
 
     @Test
-    public void test_writeArray_int() {
+    void test_writeArray_int() {
         final int[] items = {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_long() {
-        expectNull(() -> WRITER.writeArray((long[]) null));
+    void test_writeArray_null_long() {
+        expectNull(writer -> writer.writeArray((long[]) null));
     }
 
     @Test
-    public void test_writeArray_long() {
+    void test_writeArray_long() {
         final long[] items = {Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_float() {
-        expectNull(() -> WRITER.writeArray((float[]) null));
+    void test_writeArray_null_float() {
+        expectNull(writer -> writer.writeArray((float[]) null));
     }
 
     @Test
-    public void test_writeArray_float() {
+    void test_writeArray_float() {
         final float[] items = {Float.MIN_VALUE, -1F, 0F, 1F, Float.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_double() {
-        expectNull(() -> WRITER.writeArray((double[]) null));
+    void test_writeArray_null_double() {
+        expectNull(writer -> writer.writeArray((double[]) null));
     }
 
     @Test
-    public void test_writeArray_double() {
+    void test_writeArray_double() {
         final double[] items = {Double.MIN_VALUE, -1D, 0D, 1D, Double.MAX_VALUE};
         final String expectedJson = Arrays
                 .toString(items)
                 .replaceAll(" ", "");
-        final String actualJson = WRITER.use(() -> WRITER.writeArray(items));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeArray(items)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeArray_null_Object() {
-        expectNull(() -> WRITER.writeArray((Object[]) null));
+    void test_writeArray_null_Object() {
+        expectNull(writer -> writer.writeArray((Object[]) null));
     }
 
     @Test
-    public void test_writeArray_Object() {
+    void test_writeArray_Object() {
         final String expectedJson = "[\"foo\",{\"bar\":\"buzz\"},null]";
-        final String actualJson = WRITER.use(() ->
-                WRITER.writeArray(new Object[]{
-                        "foo",
-                        Collections.singletonMap("bar", "buzz"),
-                        null
-                }));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() ->
+                        writer.writeArray(new Object[]{
+                                "foo",
+                                Collections.singletonMap("bar", "buzz"),
+                                null
+                        })));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeString_null_emitter() {
+    void test_writeString_null_emitter() {
         Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() -> WRITER.writeString(null, 0L)))
+                        withLockedWriter(writer ->
+                                writer.use(() ->
+                                        writer.writeString(null, 0L))))
                 .isInstanceOf(NullPointerException.class)
                 .hasMessageContaining("emitter");
     }
 
     @Test
-    public void test_writeString_emitter() {
+    void test_writeString_emitter() {
         final String state = "there-is-no-spoon";
         final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
         final String expectedJson = '"' + state + '"';
-        final String actualJson =
-                WRITER.use(() -> WRITER.writeString(emitter, state));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeString(emitter, state)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeString_emitter_excessive_string() {
-        final int maxStringLength = WRITER.getMaxStringLength();
-        final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
-        final String expectedJson = '"' +
-                excessiveString.substring(0, maxStringLength) +
-                WRITER.getTruncatedStringSuffix() +
-                '"';
-        final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
-        final String actualJson =
-                WRITER.use(() -> WRITER.writeString(emitter, excessiveString));
-        Assertions.assertThat(actualJson).isEqualTo(expectedJson);
-    }
-
-    @Test
-    public void test_writeString_null_formattable() {
-        expectNull(() -> WRITER.writeString((StringBuilderFormattable) null));
-    }
-
-    @Test
-    public void test_writeString_formattable() {
-        final String expectedJson = "\"foo\\tbar\\tbuzz\"";
-        final String actualJson = WRITER.use(() ->
-                WRITER.writeString(stringBuilder -> stringBuilder.append("foo\tbar\tbuzz")));
-        Assertions.assertThat(actualJson).isEqualTo(expectedJson);
-    }
-
-    @Test
-    public void test_writeString_formattable_excessive_string() {
-        final int maxStringLength = WRITER.getMaxStringLength();
-        final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
-        final String expectedJson = '"' +
-                excessiveString.substring(0, maxStringLength) +
-                WRITER.getTruncatedStringSuffix() +
-                '"';
-        final String actualJson = WRITER.use(() ->
-                WRITER.writeString(stringBuilder -> stringBuilder.append(excessiveString)));
-        Assertions.assertThat(actualJson).isEqualTo(expectedJson);
-    }
-
-    @Test
-    public void test_writeString_null_seq_1() {
-        expectNull(() -> WRITER.writeString((CharSequence) null));
-    }
-
-    @Test
-    public void test_writeString_null_seq_2() {
-        expectNull(() -> WRITER.writeString((CharSequence) null, 0, 4));
-    }
-
-    @Test
-    public void test_writeString_seq_negative_offset() {
-        Assertions
-                .assertThatThrownBy(() ->
-                        WRITER.use(() -> WRITER.writeString("a", -1, 0)))
-                .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("offset");
-    }
-
-    @Test
-    public void test_writeString_seq_negative_length() {
-        Assertions
-                .assertThatThrownBy(() ->
-                        WRITER.use(() -> WRITER.writeString("a", 0, -1)))
-                .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("length");
-    }
-
-    @Test
-    public void test_writeString_excessive_seq() {
-        final CharSequence seq = Strings.repeat("x", WRITER.getMaxStringLength()) + 'y';
-        final String expectedJson = "\"" +
-                Strings.repeat("x", WRITER.getMaxStringLength()) +
-                WRITER.getTruncatedStringSuffix() +
-                '"';
-        final String actualJson = WRITER.use(() -> WRITER.writeString(seq));
-        Assertions.assertThat(actualJson).isEqualTo(expectedJson);
-    }
-
-    @Test
-    public void test_writeString_seq() throws IOException {
-        testQuoting((final Character c) -> {
-            final String s = "" + c;
-            return WRITER.use(() -> WRITER.writeString(s));
+    void test_writeString_emitter_excessive_string() {
+        withLockedWriter(writer -> {
+            final int maxStringLength = writer.getMaxStringLength();
+            final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
+            final String expectedJson = '"' +
+                    excessiveString.substring(0, maxStringLength) +
+                    writer.getTruncatedStringSuffix() +
+                    '"';
+            final BiConsumer<StringBuilder, String> emitter = StringBuilder::append;
+            final String actualJson =
+                    writer.use(() -> writer.writeString(emitter, excessiveString));
+            Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         });
     }
 
     @Test
-    public void test_writeString_null_buffer_1() {
-        expectNull(() -> WRITER.writeString((char[]) null));
+    void test_writeString_null_formattable() {
+        expectNull(writer -> writer.writeString((StringBuilderFormattable) null));
     }
 
     @Test
-    public void test_writeString_null_buffer_2() {
-        expectNull(() -> WRITER.writeString((char[]) null, 0, 4));
-    }
-
-    @Test
-    public void test_writeString_buffer_negative_offset() {
-        Assertions
-                .assertThatThrownBy(() ->
-                        WRITER.use(() -> WRITER.writeString(new char[]{'a'}, -1, 0)))
-                .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("offset");
-    }
-
-    @Test
-    public void test_writeString_buffer_negative_length() {
-        Assertions
-                .assertThatThrownBy(() ->
-                        WRITER.use(() -> WRITER.writeString(new char[]{'a'}, 0, -1)))
-                .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("length");
-    }
-
-    @Test
-    public void test_writeString_excessive_buffer() {
-        final char[] buffer =
-                (Strings.repeat("x", WRITER.getMaxStringLength()) + 'y')
-                        .toCharArray();
-        final String expectedJson = "\"" +
-                Strings.repeat("x", WRITER.getMaxStringLength()) +
-                WRITER.getTruncatedStringSuffix() +
-                '"';
-        final String actualJson = WRITER.use(() -> WRITER.writeString(buffer));
+    void test_writeString_formattable() {
+        final String expectedJson = "\"foo\\tbar\\tbuzz\"";
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() ->
+                        writer.writeString(stringBuilder ->
+                                stringBuilder.append("foo\tbar\tbuzz"))));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeString_buffer() throws IOException {
+    void test_writeString_formattable_excessive_string() {
+        withLockedWriter(writer -> {
+            final int maxStringLength = writer.getMaxStringLength();
+            final String excessiveString = Strings.repeat("x", maxStringLength) + 'y';
+            final String expectedJson = '"' +
+                    excessiveString.substring(0, maxStringLength) +
+                    writer.getTruncatedStringSuffix() +
+                    '"';
+            final String actualJson = writer.use(() ->
+                    writer.writeString(stringBuilder ->
+                            stringBuilder.append(excessiveString)));
+            Assertions.assertThat(actualJson).isEqualTo(expectedJson);
+        });
+    }
+
+    @Test
+    void test_writeString_null_seq_1() {
+        expectNull(writer -> writer.writeString((CharSequence) null));
+    }
+
+    @Test
+    void test_writeString_null_seq_2() {
+        expectNull(writer -> writer.writeString((CharSequence) null, 0, 4));
+    }
+
+    @Test
+    void test_writeString_seq_negative_offset() {
+        withLockedWriter(writer -> Assertions
+                .assertThatThrownBy(() ->
+                        writer.use(() -> writer.writeString("a", -1, 0)))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("offset"));
+    }
+
+    @Test
+    void test_writeString_seq_negative_length() {
+        withLockedWriter(writer -> Assertions
+                .assertThatThrownBy(() ->
+                        writer.use(() -> writer.writeString("a", 0, -1)))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("length"));
+    }
+
+    @Test
+    void test_writeString_excessive_seq() {
+        withLockedWriter(writer -> {
+            final CharSequence seq = Strings.repeat("x", writer.getMaxStringLength()) + 'y';
+            final String expectedJson = "\"" +
+                    Strings.repeat("x", writer.getMaxStringLength()) +
+                    writer.getTruncatedStringSuffix() +
+                    '"';
+            final String actualJson = writer.use(() -> writer.writeString(seq));
+            Assertions.assertThat(actualJson).isEqualTo(expectedJson);
+        });
+    }
+
+    @Test
+    void test_writeString_seq() throws IOException {
+        testQuoting((final Character c) -> {
+            final String s = "" + c;
+            return withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeString(s)));
+        });
+    }
+
+    @Test
+    void test_writeString_null_buffer_1() {
+        expectNull(writer -> writer.writeString((char[]) null));
+    }
+
+    @Test
+    void test_writeString_null_buffer_2() {
+        expectNull(writer -> writer.writeString((char[]) null, 0, 4));
+    }
+
+    @Test
+    void test_writeString_buffer_negative_offset() {
+        withLockedWriter(writer -> Assertions
+                .assertThatThrownBy(() ->
+                        writer.use(() -> writer.writeString(new char[]{'a'}, -1, 0)))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("offset"));
+    }
+
+    @Test
+    void test_writeString_buffer_negative_length() {
+        withLockedWriter(writer -> Assertions
+                .assertThatThrownBy(() ->
+                        writer.use(() -> writer.writeString(new char[]{'a'}, 0, -1)))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("length"));
+    }
+
+    @Test
+    void test_writeString_excessive_buffer() {
+        withLockedWriter(writer -> {
+            final char[] buffer =
+                    (Strings.repeat("x", writer.getMaxStringLength()) + 'y')
+                            .toCharArray();
+            final String expectedJson = "\"" +
+                    Strings.repeat("x", writer.getMaxStringLength()) +
+                    writer.getTruncatedStringSuffix() +
+                    '"';
+            final String actualJson = writer.use(() -> writer.writeString(buffer));
+            Assertions.assertThat(actualJson).isEqualTo(expectedJson);
+        });
+    }
+
+    @Test
+    void test_writeString_buffer() throws IOException {
         final char[] buffer = new char[1];
         testQuoting((final Character c) -> {
             buffer[0] = c;
-            return WRITER.use(() -> WRITER.writeString(buffer));
+            return withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeString(buffer)));
         });
     }
 
-    private void testQuoting(
+    private static void testQuoting(
             final Function<Character, String> quoter) throws IOException {
         final SoftAssertions assertions = new SoftAssertions();
         for (char c = Character.MIN_VALUE;; c++) {
@@ -511,12 +556,12 @@
     }
 
     @Test
-    public void test_writeNumber_null_BigDecimal() {
-        expectNull(() -> WRITER.writeNumber((BigDecimal) null));
+    void test_writeNumber_null_BigDecimal() {
+        expectNull(writer -> writer.writeNumber((BigDecimal) null));
     }
 
     @Test
-    public void test_writeNumber_BigDecimal() {
+    void test_writeNumber_BigDecimal() {
         for (final BigDecimal number : new BigDecimal[]{
                 BigDecimal.ZERO,
                 BigDecimal.ONE,
@@ -526,191 +571,209 @@
                         '.' + Long.MAX_VALUE +
                         "" + Long.MAX_VALUE)}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_null_BigInteger() {
-        expectNull(() -> WRITER.writeNumber((BigInteger) null));
+    void test_writeNumber_null_BigInteger() {
+        expectNull(writer -> writer.writeNumber((BigInteger) null));
     }
 
     @Test
-    public void test_writeNumber_BigInteger() {
+    void test_writeNumber_BigInteger() {
         for (final BigInteger number : new BigInteger[]{
                 BigInteger.ZERO,
                 BigInteger.ONE,
                 BigInteger.TEN,
                 new BigInteger("" + Long.MAX_VALUE + "" + Long.MAX_VALUE)}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_float() {
+    void test_writeNumber_float() {
         for (final float number : new float[]{Float.MIN_VALUE, -1.0F, 0F, 1.0F, Float.MAX_VALUE}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_double() {
+    void test_writeNumber_double() {
         for (final double number : new double[]{Double.MIN_VALUE, -1.0D, 0D, 1.0D, Double.MAX_VALUE}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_short() {
+    void test_writeNumber_short() {
         for (final short number : new short[]{Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_int() {
+    void test_writeNumber_int() {
         for (final int number : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_long() {
+    void test_writeNumber_long() {
         for (final long number : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) {
             final String expectedJson = String.valueOf(number);
-            final String actualJson = WRITER.use(() -> WRITER.writeNumber(number));
+            final String actualJson = withLockedWriterReturning(writer ->
+                    writer.use(() -> writer.writeNumber(number)));
             Assertions.assertThat(actualJson).isEqualTo(expectedJson);
         }
     }
 
     @Test
-    public void test_writeNumber_integral_and_negative_fractional() {
+    void test_writeNumber_integral_and_negative_fractional() {
         Assertions
-                .assertThatThrownBy(() -> WRITER.use(() -> WRITER.writeNumber(0, -1)))
+                .assertThatThrownBy(() ->
+                        withLockedWriter(writer ->
+                                writer.use(() -> writer.writeNumber(0, -1))))
                 .isInstanceOf(IllegalArgumentException.class)
                 .hasMessage("was expecting a positive fraction: -1");
     }
 
     @Test
-    public void test_writeNumber_integral_and_zero_fractional() {
+    void test_writeNumber_integral_and_zero_fractional() {
         final String expectedJson = "123";
-        final String actualJson = WRITER.use(() -> WRITER.writeNumber(123L, 0L));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeNumber(123L, 0L)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeNumber_integral_and_fractional() {
+    void test_writeNumber_integral_and_fractional() {
         final String expectedJson = "123.456";
-        final String actualJson = WRITER.use(() -> WRITER.writeNumber(123L, 456L));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeNumber(123L, 456L)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeBoolean_true() {
+    void test_writeBoolean_true() {
         final String expectedJson = "true";
-        final String actualJson = WRITER.use(() -> WRITER.writeBoolean(true));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeBoolean(true)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeBoolean_false() {
+    void test_writeBoolean_false() {
         final String expectedJson = "false";
-        final String actualJson = WRITER.use(() -> WRITER.writeBoolean(false));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeBoolean(false)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeNull() {
-        expectNull(WRITER::writeNull);
+    void test_writeNull() {
+        expectNull(JsonWriter::writeNull);
     }
 
-    private void expectNull(Runnable body) {
+    private void expectNull(Consumer<JsonWriter> body) {
         final String expectedJson = "null";
-        final String actualJson = WRITER.use(body);
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> body.accept(writer)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeRawString_null_seq() {
-        Assertions
+    void test_writeRawString_null_seq() {
+        withLockedWriter(writer -> Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() ->
-                                WRITER.writeRawString((String) null)))
+                        writer.use(() ->
+                                writer.writeRawString((String) null)))
                 .isInstanceOf(NullPointerException.class)
-                .hasMessage("seq");
+                .hasMessage("seq"));
     }
 
     @Test
-    public void test_writeRawString_seq_negative_offset() {
-        Assertions
+    void test_writeRawString_seq_negative_offset() {
+        withLockedWriter(writer -> Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() ->
-                                WRITER.writeRawString("a", -1, 0)))
+                        writer.use(() ->
+                                writer.writeRawString("a", -1, 0)))
                 .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("offset");
+                .hasMessageContaining("offset"));
     }
 
     @Test
-    public void test_writeRawString_seq_negative_length() {
-        Assertions
+    void test_writeRawString_seq_negative_length() {
+        withLockedWriter(writer -> Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() ->
-                                WRITER.writeRawString("a", 0, -1)))
+                        writer.use(() ->
+                                writer.writeRawString("a", 0, -1)))
                 .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("length");
+                .hasMessageContaining("length"));
     }
 
     @Test
-    public void test_writeRawString_seq() {
+    void test_writeRawString_seq() {
         final String expectedJson = "this is not a valid JSON string";
-        final String actualJson = WRITER.use(() -> WRITER.writeRawString(expectedJson));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() -> writer.writeRawString(expectedJson)));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
     @Test
-    public void test_writeRawString_null_buffer() {
-        Assertions
-                .assertThatThrownBy(() -> WRITER.use(() ->
-                        WRITER.writeRawString((char[]) null)))
+    void test_writeRawString_null_buffer() {
+        withLockedWriter(writer -> Assertions
+                .assertThatThrownBy(() ->
+                        writer.use(() ->
+                                writer.writeRawString((char[]) null)))
                 .isInstanceOf(NullPointerException.class)
-                .hasMessage("buffer");
+                .hasMessage("buffer"));
     }
 
     @Test
-    public void test_writeRawString_buffer_negative_offset() {
-        Assertions
+    void test_writeRawString_buffer_negative_offset() {
+        withLockedWriter(writer -> Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() ->
-                                WRITER.writeRawString(new char[]{'a'}, -1, 0)))
+                        writer.use(() ->
+                                writer.writeRawString(new char[]{'a'}, -1, 0)))
                 .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("offset");
+                .hasMessageContaining("offset"));
     }
 
     @Test
-    public void test_writeRawString_buffer_negative_length() {
-        Assertions
+    void test_writeRawString_buffer_negative_length() {
+        withLockedWriter(writer -> Assertions
                 .assertThatThrownBy(() ->
-                        WRITER.use(() ->
-                                WRITER.writeRawString(new char[]{'a'}, 0, -1)))
+                        writer.use(() ->
+                                writer.writeRawString(new char[]{'a'}, 0, -1)))
                 .isInstanceOf(IllegalArgumentException.class)
-                .hasMessageContaining("length");
+                .hasMessageContaining("length"));
     }
 
     @Test
-    public void test_writeRawString_buffer() {
+    void test_writeRawString_buffer() {
         final String expectedJson = "this is not a valid JSON string";
-        final String actualJson = WRITER.use(() -> WRITER.writeRawString(expectedJson.toCharArray()));
+        final String actualJson = withLockedWriterReturning(writer ->
+                writer.use(() ->
+                        writer.writeRawString(expectedJson.toCharArray())));
         Assertions.assertThat(actualJson).isEqualTo(expectedJson);
     }
 
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
index 95cd0dd..fdb71bf 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
@@ -19,15 +19,15 @@
 import org.apache.logging.log4j.plugins.convert.TypeConverter;
 import org.apache.logging.log4j.plugins.convert.TypeConverterRegistry;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.ArrayDeque;
 import java.util.concurrent.ArrayBlockingQueue;
 
-public class RecyclerFactoriesTest {
+class RecyclerFactoriesTest {
 
     @Test
-    public void test_RecyclerFactoryConverter() throws Exception {
+    void test_RecyclerFactoryConverter() throws Exception {
 
         // Check if the type converter is registered.
         final TypeConverter<?> converter = TypeConverterRegistry
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParserTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParserTest.java
index 601c578..92bbe55 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParserTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/StringParameterParserTest.java
@@ -22,7 +22,7 @@
 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Value;
 import org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values;
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -30,66 +30,67 @@
 import java.util.Map;
 import java.util.Set;
 
-public class StringParameterParserTest {
+@SuppressWarnings("DoubleBraceInitialization")
+class StringParameterParserTest {
 
     @Test
-    public void test_empty_string() {
+    void test_empty_string() {
         testSuccess(
                 "",
                 Collections.emptyMap());
     }
 
     @Test
-    public void test_blank_string() {
+    void test_blank_string() {
         testSuccess(
                 "\t",
                 Collections.emptyMap());
     }
 
     @Test
-    public void test_simple_pair() {
+    void test_simple_pair() {
         testSuccess(
                 "a=b",
                 Collections.singletonMap("a", Values.stringValue("b")));
     }
 
     @Test
-    public void test_simple_pair_with_whitespace_1() {
+    void test_simple_pair_with_whitespace_1() {
         testSuccess(
                 " a=b",
                 Collections.singletonMap("a", Values.stringValue("b")));
     }
 
     @Test
-    public void test_simple_pair_with_whitespace_2() {
+    void test_simple_pair_with_whitespace_2() {
         testSuccess(
                 " a =b",
                 Collections.singletonMap("a", Values.stringValue("b")));
     }
 
     @Test
-    public void test_simple_pair_with_whitespace_3() {
+    void test_simple_pair_with_whitespace_3() {
         testSuccess(
                 " a = b",
                 Collections.singletonMap("a", Values.stringValue("b")));
     }
 
     @Test
-    public void test_simple_pair_with_whitespace_4() {
+    void test_simple_pair_with_whitespace_4() {
         testSuccess(
                 " a = b ",
                 Collections.singletonMap("a", Values.stringValue("b")));
     }
 
     @Test
-    public void test_null_value_1() {
+    void test_null_value_1() {
         testSuccess(
                 "a",
                 Collections.singletonMap("a", Values.nullValue()));
     }
 
     @Test
-    public void test_null_value_2() {
+    void test_null_value_2() {
         testSuccess(
                 "a,b=c,d=",
                 new LinkedHashMap<String, Value>() {{
@@ -100,7 +101,7 @@
     }
 
     @Test
-    public void test_null_value_3() {
+    void test_null_value_3() {
         testSuccess(
                 "a,b=c,d",
                 new LinkedHashMap<String, Value>() {{
@@ -111,7 +112,7 @@
     }
 
     @Test
-    public void test_null_value_4() {
+    void test_null_value_4() {
         testSuccess(
                 "a,b=\"c,=\\\"\",d=,e=f",
                 new LinkedHashMap<String, Value>() {{
@@ -123,7 +124,7 @@
     }
 
     @Test
-    public void test_two_pairs() {
+    void test_two_pairs() {
         testSuccess(
                 "a=b,c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -133,14 +134,14 @@
     }
 
     @Test
-    public void test_quoted_string_01() {
+    void test_quoted_string_01() {
         testSuccess(
                 "a=\"b\"",
                 Collections.singletonMap("a", Values.doubleQuotedStringValue("b")));
     }
 
     @Test
-    public void test_quoted_string_02() {
+    void test_quoted_string_02() {
         testSuccess(
                 "a=\"b\",c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -150,7 +151,7 @@
     }
 
     @Test
-    public void test_quoted_string_03() {
+    void test_quoted_string_03() {
         testSuccess(
                 "a=b,c=\"d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -160,7 +161,7 @@
     }
 
     @Test
-    public void test_quoted_string_04() {
+    void test_quoted_string_04() {
         testSuccess(
                 "a=\"b\",c=\"d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -170,21 +171,21 @@
     }
 
     @Test
-    public void test_quoted_string_05() {
+    void test_quoted_string_05() {
         testSuccess(
                 "a=\"\\\"b\"",
                 Collections.singletonMap("a", Values.doubleQuotedStringValue("\"b")));
     }
 
     @Test
-    public void test_quoted_string_06() {
+    void test_quoted_string_06() {
         testSuccess(
                 "a=\"\\\"b\\\"\"",
                 Collections.singletonMap("a", Values.doubleQuotedStringValue("\"b\"")));
     }
 
     @Test
-    public void test_quoted_string_07() {
+    void test_quoted_string_07() {
         testSuccess(
                 "a=\"\\\"b\",c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -194,7 +195,7 @@
     }
 
     @Test
-    public void test_quoted_string_08() {
+    void test_quoted_string_08() {
         testSuccess(
                 "a=\"\\\"b\\\"\",c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -204,7 +205,7 @@
     }
 
     @Test
-    public void test_quoted_string_09() {
+    void test_quoted_string_09() {
         testSuccess(
                 "a=\"\\\"b,\",c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -214,7 +215,7 @@
     }
 
     @Test
-    public void test_quoted_string_10() {
+    void test_quoted_string_10() {
         testSuccess(
                 "a=\"\\\"b\\\",\",c=d",
                 new LinkedHashMap<String, Value>() {{
@@ -224,7 +225,7 @@
     }
 
     @Test
-    public void test_quoted_string_11() {
+    void test_quoted_string_11() {
         testSuccess(
                 "a=\"\\\"b\",c=\"d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -234,7 +235,7 @@
     }
 
     @Test
-    public void test_quoted_string_12() {
+    void test_quoted_string_12() {
         testSuccess(
                 "a=\"\\\"b\\\"\",c=\"d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -244,7 +245,7 @@
     }
 
     @Test
-    public void test_quoted_string_13() {
+    void test_quoted_string_13() {
         testSuccess(
                 "a=\"\\\"b,\",c=\"\\\"d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -254,7 +255,7 @@
     }
 
     @Test
-    public void test_quoted_string_14() {
+    void test_quoted_string_14() {
         testSuccess(
                 "a=\"\\\"b\\\",\",c=\"\\\"d\\\"\"",
                 new LinkedHashMap<String, Value>() {{
@@ -264,7 +265,7 @@
     }
 
     @Test
-    public void test_quoted_string_15() {
+    void test_quoted_string_15() {
         testSuccess(
                 "a=\"\\\"b\",c=\",d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -274,7 +275,7 @@
     }
 
     @Test
-    public void test_quoted_string_16() {
+    void test_quoted_string_16() {
         testSuccess(
                 "a=\"\\\"b\\\"\",c=\",d\"",
                 new LinkedHashMap<String, Value>() {{
@@ -284,7 +285,7 @@
     }
 
     @Test
-    public void test_quoted_string_17() {
+    void test_quoted_string_17() {
         testSuccess(
                 "a=\"\\\"b,\",c=\"\\\"d,\"",
                 new LinkedHashMap<String, Value>() {{
@@ -294,7 +295,7 @@
     }
 
     @Test
-    public void test_quoted_string_18() {
+    void test_quoted_string_18() {
         testSuccess(
                 "a=\"\\\"b\\\",\",c=\"\\\"d\\\",\"",
                 new LinkedHashMap<String, Value>() {{
@@ -314,7 +315,7 @@
     }
 
     @Test
-    public void test_missing_key() {
+    void test_missing_key() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = ",a=b";
@@ -324,7 +325,7 @@
     }
 
     @Test
-    public void test_conflicting_key() {
+    void test_conflicting_key() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,a";
@@ -334,7 +335,7 @@
     }
 
     @Test
-    public void test_prematurely_ending_quoted_string_01() {
+    void test_prematurely_ending_quoted_string_01() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,b=\"";
@@ -344,7 +345,7 @@
     }
 
     @Test
-    public void test_prematurely_ending_quoted_string_02() {
+    void test_prematurely_ending_quoted_string_02() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,b=\"c";
@@ -354,7 +355,7 @@
     }
 
     @Test
-    public void test_prematurely_ending_quoted_string_03() {
+    void test_prematurely_ending_quoted_string_03() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,b=\",c";
@@ -364,7 +365,7 @@
     }
 
     @Test
-    public void test_prematurely_ending_quoted_string_04() {
+    void test_prematurely_ending_quoted_string_04() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,b=\",c\" x";
@@ -374,28 +375,28 @@
     }
 
     @Test
-    public void test_NullValue_toString() {
+    void test_NullValue_toString() {
         final Map<String, Value> map = StringParameterParser.parse("a");
         final NullValue value = (NullValue) map.get("a");
         Assertions.assertThat(value.toString()).isEqualTo(null);
     }
 
     @Test
-    public void test_StringValue_toString() {
+    void test_StringValue_toString() {
         final Map<String, Value> map = StringParameterParser.parse("a=b");
         final StringValue value = (StringValue) map.get("a");
         Assertions.assertThat(value.toString()).isEqualTo("b");
     }
 
     @Test
-    public void test_DoubleQuotedStringValue_toString() {
+    void test_DoubleQuotedStringValue_toString() {
         final Map<String, Value> map = StringParameterParser.parse("a=\"\\\"b\"");
         final DoubleQuotedStringValue value = (DoubleQuotedStringValue) map.get("a");
         Assertions.assertThat(value.toString()).isEqualTo("\"b");
     }
 
     @Test
-    public void test_allowedKeys() {
+    void test_allowedKeys() {
         Assertions
                 .assertThatThrownBy(() -> {
                     final String input = "a,b";
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriterTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriterTest.java
index 6e46197..a8b210c 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriterTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/TruncatingBufferedWriterTest.java
@@ -17,19 +17,19 @@
 package org.apache.logging.log4j.layout.template.json.util;
 
 import org.assertj.core.api.Assertions;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-public class TruncatingBufferedWriterTest {
+class TruncatingBufferedWriterTest {
 
     @Test
-    public void test_ctor_invalid_args() {
+    void test_ctor_invalid_args() {
         Assertions
                 .assertThatThrownBy(() -> new TruncatingBufferedWriter(-1))
                 .isInstanceOf(NegativeArraySizeException.class);
     }
 
     @Test
-    public void test_okay_payloads() {
+    void test_okay_payloads() {
 
         // Fill in the writer.
         final int capacity = 1_000;
@@ -84,7 +84,7 @@
     }
 
     @Test
-    public void test_write_int_truncation() {
+    void test_write_int_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.write('a');
         writer.write('b');
@@ -92,21 +92,21 @@
     }
 
     @Test
-    public void test_write_char_array_truncation() {
+    void test_write_char_array_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.write(new char[]{'a', 'b'});
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_write_String_truncation() {
+    void test_write_String_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.write("ab");
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_write_String_slice_invalid_args() {
+    void test_write_String_slice_invalid_args() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         final String string = "a";
         Assertions
@@ -128,14 +128,14 @@
     }
 
     @Test
-    public void test_write_String_slice_truncation() {
+    void test_write_String_slice_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.write("ab", 0, 2);
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_write_char_array_slice_invalid_args() {
+    void test_write_char_array_slice_invalid_args() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         final char[] buffer = new char[]{'a'};
         Assertions
@@ -157,14 +157,14 @@
     }
 
     @Test
-    public void test_write_char_array_slice_truncation() {
+    void test_write_char_array_slice_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.write(new char[]{'a', 'b'}, 0, 2);
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_append_char_truncation() {
+    void test_append_char_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.append('a');
         writer.append('b');
@@ -172,21 +172,21 @@
     }
 
     @Test
-    public void test_append_seq_truncation() {
+    void test_append_seq_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.append("ab");
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_append_seq_null_truncation() {
+    void test_append_seq_null_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.append(null);
         verifyTruncation(writer, 'n');
     }
 
     @Test
-    public void test_append_seq_slice_invalid_args() {
+    void test_append_seq_slice_invalid_args() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         final CharSequence seq = "ab";
         Assertions
@@ -212,14 +212,14 @@
     }
 
     @Test
-    public void test_append_seq_slice_truncation() {
+    void test_append_seq_slice_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.append("ab", 0, 1);
         verifyTruncation(writer, 'a');
     }
 
     @Test
-    public void test_append_seq_slice_null_truncation() {
+    void test_append_seq_slice_null_truncation() {
         final TruncatingBufferedWriter writer = new TruncatingBufferedWriter(1);
         writer.append(null, -1, -1);
         verifyTruncation(writer, 'n');
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/UrisTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/UrisTest.java
index 7b0d1da..e5282db 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/UrisTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/UrisTest.java
@@ -18,8 +18,8 @@
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.junit.Assert;
-import org.junit.Test;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -29,22 +29,20 @@
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 
-public class UrisTest {
+class UrisTest {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
     @Test
-    public void testClassPathResource() {
+    void testClassPathResource() {
         final String content = Uris.readUri(
                 "classpath:JsonLayout.json",
                 StandardCharsets.US_ASCII);
-        Assert.assertTrue(
-                "was expecting content to start with '{': " + content,
-                content.startsWith("{"));
+        Assertions.assertThat(content).startsWith("{");
     }
 
     @Test
-    public void testFilePathResource() throws IOException {
+    void testFilePathResource() throws IOException {
         final String nonAsciiUtfText = "அஆஇฬ๘";
         final File file = Files.createTempFile("log4j-UriUtilTest-", ".txt").toFile();
         try {
@@ -53,7 +51,7 @@
             }
             final URI uri = file.toURI();
             final String content = Uris.readUri(uri, StandardCharsets.UTF_8);
-            Assert.assertEquals(nonAsciiUtfText, content);
+            Assertions.assertThat(content).isEqualTo(nonAsciiUtfText);
         } finally {
             final boolean deleted = file.delete();
             if (!deleted) {