You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cl...@apache.org on 2023/08/16 15:29:12 UTC

[avro] branch master updated: AVRO-3829: [Java] Junit5 (#2445)

This is an automated email from the ASF dual-hosted git repository.

clesaec pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 957a25b1c AVRO-3829: [Java] Junit5 (#2445)
957a25b1c is described below

commit 957a25b1c37dbe5b56d85291a22f4f57577cb647
Author: Christophe Le Saec <51...@users.noreply.github.com>
AuthorDate: Wed Aug 16 17:29:06 2023 +0200

    AVRO-3829: [Java] Junit5 (#2445)
    
    * AVRO-3829: To JUnit5
---
 .../java/org/apache/avro/TestDataFileConcat.java   |  73 ++--
 .../TestReadingWritingDataInEvolvedSchemas.java    | 293 +++++++-------
 .../org/apache/avro/TestSchemaCompatibility.java   |  10 +-
 .../TestSchemaCompatibilityFixedSizeMismatch.java  |  52 ++-
 .../TestSchemaCompatibilityMissingEnumSymbols.java |  45 +--
 .../TestSchemaCompatibilityMissingUnionBranch.java | 129 ++++---
 .../avro/TestSchemaCompatibilityNameMismatch.java  |  51 ++-
 ...ompatibilityReaderFieldMissingDefaultValue.java |  43 +--
 .../avro/TestSchemaCompatibilityTypeMismatch.java  | 124 +++---
 .../java/org/apache/avro/file/TestAllCodecs.java   |  58 ++-
 .../java/org/apache/avro/io/TestBinaryDecoder.java | 419 +++++++++++----------
 .../java/org/apache/avro/io/TestBlockingIO.java    |  65 ++--
 .../java/org/apache/avro/io/TestBlockingIO2.java   |  38 +-
 .../java/org/apache/avro/io/TestResolvingIO.java   |  55 +--
 .../apache/avro/io/TestResolvingIOResolving.java   |  59 +--
 .../java/org/apache/avro/io/TestValidatingIO.java  | 114 +++---
 .../io/parsing/TestResolvingGrammarGenerator.java  |  61 +--
 .../avro/specific/TestSpecificRecordWithUnion.java |   5 +-
 .../org/apache/avro/tool/TestRpcProtocolTool.java  |  51 +--
 .../test/java/org/apache/trevni/TestAllCodecs.java |  29 +-
 .../java/org/apache/trevni/TestColumnFile.java     | 129 ++++---
 21 files changed, 897 insertions(+), 1006 deletions(-)

diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestDataFileConcat.java b/lang/java/avro/src/test/java/org/apache/avro/TestDataFileConcat.java
index f1267ab97..1aeebcdda 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestDataFileConcat.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestDataFileConcat.java
@@ -17,60 +17,42 @@
  */
 package org.apache.avro;
 
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.avro.file.CodecFactory;
 import org.apache.avro.file.DataFileReader;
 import org.apache.avro.file.DataFileWriter;
 import org.apache.avro.generic.GenericDatumReader;
 import org.apache.avro.generic.GenericDatumWriter;
 import org.apache.avro.util.RandomData;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
+
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@RunWith(Parameterized.class)
-public class TestDataFileConcat {
-  private static final Logger LOG = LoggerFactory.getLogger(TestDataFileConcat.class);
-
-  @Rule
-  public TemporaryFolder DIR = new TemporaryFolder();
+import java.io.File;
+import java.io.IOException;
+import java.util.stream.Stream;
 
-  CodecFactory codec;
-  CodecFactory codec2;
-  boolean recompress;
+import static org.junit.Assert.assertEquals;
 
-  public TestDataFileConcat(CodecFactory codec, CodecFactory codec2, Boolean recompress) {
-    this.codec = codec;
-    this.codec2 = codec2;
-    this.recompress = recompress;
-    LOG.info("Testing concatenating files, " + codec2 + " into " + codec + " with recompress=" + recompress);
-  }
+public class TestDataFileConcat {
+  private static final Logger LOG = LoggerFactory.getLogger(TestDataFileConcat.class);
 
-  @Parameters
-  public static List<Object[]> codecs() {
-    List<Object[]> r = new ArrayList<>();
-    r.add(new Object[] { null, null, false });
-    r.add(new Object[] { null, null, true });
-    r.add(new Object[] { CodecFactory.deflateCodec(1), CodecFactory.deflateCodec(6), false });
-    r.add(new Object[] { CodecFactory.deflateCodec(1), CodecFactory.deflateCodec(6), true });
-    r.add(new Object[] { CodecFactory.deflateCodec(3), CodecFactory.nullCodec(), false });
-    r.add(new Object[] { CodecFactory.nullCodec(), CodecFactory.deflateCodec(6), false });
-    r.add(new Object[] { CodecFactory.xzCodec(1), CodecFactory.xzCodec(2), false });
-    r.add(new Object[] { CodecFactory.xzCodec(1), CodecFactory.xzCodec(2), true });
-    r.add(new Object[] { CodecFactory.xzCodec(2), CodecFactory.nullCodec(), false });
-    r.add(new Object[] { CodecFactory.nullCodec(), CodecFactory.xzCodec(2), false });
-    return r;
+  @TempDir
+  public File DIR;
+
+  public static Stream<Arguments> codecs() {
+    return Stream.of(Arguments.of(null, null, false), Arguments.of(null, null, true),
+        Arguments.of(CodecFactory.deflateCodec(1), CodecFactory.deflateCodec(6), false),
+        Arguments.of(CodecFactory.deflateCodec(1), CodecFactory.deflateCodec(6), true),
+        Arguments.of(CodecFactory.deflateCodec(3), CodecFactory.nullCodec(), false),
+        Arguments.of(CodecFactory.nullCodec(), CodecFactory.deflateCodec(6), false),
+        Arguments.of(CodecFactory.xzCodec(1), CodecFactory.xzCodec(2), false),
+        Arguments.of(CodecFactory.xzCodec(1), CodecFactory.xzCodec(2), true),
+        Arguments.of(CodecFactory.xzCodec(2), CodecFactory.nullCodec(), false),
+        Arguments.of(CodecFactory.nullCodec(), CodecFactory.xzCodec(2), false));
   }
 
   private static final int COUNT = Integer.parseInt(System.getProperty("test.count", "200"));
@@ -83,11 +65,12 @@ public class TestDataFileConcat {
   private static final Schema SCHEMA = new Schema.Parser().parse(SCHEMA_JSON);
 
   private File makeFile(String name) {
-    return new File(DIR.getRoot().getPath(), "test-" + name + ".avro");
+    return new File(DIR, "test-" + name + ".avro");
   }
 
-  @Test
-  public void testConcatenateFiles() throws IOException {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void concatenateFiles(CodecFactory codec, CodecFactory codec2, boolean recompress) throws IOException {
     System.out.println("SEED = " + SEED);
     System.out.println("COUNT = " + COUNT);
     for (int k = 0; k < 5; k++) {
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java b/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
index 2918f8b9e..89fedc75c 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
@@ -27,6 +27,8 @@ import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.stream.Stream;
+
 import org.apache.avro.generic.GenericData;
 import org.apache.avro.generic.GenericData.EnumSymbol;
 import org.apache.avro.generic.GenericData.Record;
@@ -38,24 +40,17 @@ import org.apache.avro.io.Decoder;
 import org.apache.avro.io.DecoderFactory;
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.EncoderFactory;
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
 public class TestReadingWritingDataInEvolvedSchemas {
 
   private static final String RECORD_A = "RecordA";
   private static final String FIELD_A = "fieldA";
   private static final char LATIN_SMALL_LETTER_O_WITH_DIARESIS = '\u00F6';
 
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
   private static final Schema DOUBLE_RECORD = SchemaBuilder.record(RECORD_A) //
       .fields() //
       .name(FIELD_A).type().doubleType().noDefault() //
@@ -127,221 +122,235 @@ public class TestReadingWritingDataInEvolvedSchemas {
       .name(FIELD_A).type().unionOf().floatType().and().doubleType().endUnion().noDefault() //
       .endRecord();
 
-  @Parameters(name = "encoder = {0}")
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new EncoderType[][] { { EncoderType.BINARY }, { EncoderType.JSON } });
-  }
-
-  public TestReadingWritingDataInEvolvedSchemas(EncoderType encoderType) {
-    this.encoderType = encoderType;
-  }
-
-  private final EncoderType encoderType;
-
   enum EncoderType {
     BINARY, JSON
   }
 
-  @Test
-  public void doubleWrittenWithUnionSchemaIsConvertedToDoubleSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void doubleWrittenWithUnionSchemaIsConvertedToDoubleSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_LONG_FLOAT_DOUBLE_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42.0);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(DOUBLE_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(DOUBLE_RECORD, writer, encoded, encoderType);
     assertEquals(42.0, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsConvertedToUnionLongFloatSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsConvertedToUnionLongFloatSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_LONG_FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_LONG_FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42L, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsConvertedToDoubleSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsConvertedToDoubleSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_DOUBLE_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_DOUBLE_RECORD, writer, encoded, encoderType);
     assertEquals(42.0, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void intWrittenWithUnionSchemaIsConvertedToDoubleSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void intWrittenWithUnionSchemaIsConvertedToDoubleSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_DOUBLE_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_DOUBLE_RECORD, writer, encoded, encoderType);
     assertEquals(42.0, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void intWrittenWithUnionSchemaIsReadableByFloatSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void intWrittenWithUnionSchemaIsReadableByFloatSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42.0f, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void intWrittenWithUnionSchemaIsReadableByFloatUnionSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void intWrittenWithUnionSchemaIsReadableByFloatUnionSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42.0f, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsReadableByFloatSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsReadableByFloatSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42.0f, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsReadableByFloatUnionSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsReadableByFloatUnionSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42.0f, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsConvertedToLongFloatUnionSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsConvertedToLongFloatUnionSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_LONG_FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_LONG_FLOAT_RECORD, writer, encoded, encoderType);
     assertEquals(42L, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsConvertedToFloatDoubleUnionSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsConvertedToFloatDoubleUnionSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_LONG_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(UNION_FLOAT_DOUBLE_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(UNION_FLOAT_DOUBLE_RECORD, writer, encoded, encoderType);
     assertEquals(42.0F, decoded.get(FIELD_A));
   }
 
-  @Test
-  public void doubleWrittenWithUnionSchemaIsNotConvertedToFloatSchema() throws Exception {
-    expectedException.expect(AvroTypeException.class);
-    expectedException.expectMessage("Found double, expecting float");
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void doubleWrittenWithUnionSchemaIsNotConvertedToFloatSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_LONG_FLOAT_DOUBLE_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42.0);
-    byte[] encoded = encodeGenericBlob(record);
-    decodeGenericBlob(FLOAT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    AvroTypeException exception = Assertions.assertThrows(AvroTypeException.class,
+        () -> decodeGenericBlob(FLOAT_RECORD, writer, encoded, encoderType));
+    Assertions.assertEquals("Found double, expecting float", exception.getMessage());
   }
 
-  @Test
-  public void floatWrittenWithUnionSchemaIsNotConvertedToLongSchema() throws Exception {
-    expectedException.expect(AvroTypeException.class);
-    expectedException.expectMessage("Found float, expecting long");
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void floatWrittenWithUnionSchemaIsNotConvertedToLongSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_LONG_FLOAT_DOUBLE_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42.0f);
-    byte[] encoded = encodeGenericBlob(record);
-    decodeGenericBlob(LONG_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    AvroTypeException exception = Assertions.assertThrows(AvroTypeException.class,
+        () -> decodeGenericBlob(LONG_RECORD, writer, encoded, encoderType));
+    Assertions.assertEquals("Found float, expecting long", exception.getMessage());
   }
 
-  @Test
-  public void longWrittenWithUnionSchemaIsNotConvertedToIntSchema() throws Exception {
-    expectedException.expect(AvroTypeException.class);
-    expectedException.expectMessage("Found long, expecting int");
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void longWrittenWithUnionSchemaIsNotConvertedToIntSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_LONG_FLOAT_DOUBLE_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42L);
-    byte[] encoded = encodeGenericBlob(record);
-    decodeGenericBlob(INT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    AvroTypeException exception = Assertions.assertThrows(AvroTypeException.class,
+        () -> decodeGenericBlob(INT_RECORD, writer, encoded, encoderType));
+    Assertions.assertEquals("Found long, expecting int", exception.getMessage());
   }
 
-  @Test
-  public void intWrittenWithUnionSchemaIsConvertedToAllNumberSchemas() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void intWrittenWithUnionSchemaIsConvertedToAllNumberSchemas(EncoderType encoderType) throws Exception {
     Schema writer = UNION_INT_LONG_FLOAT_DOUBLE_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    assertEquals(42.0, decodeGenericBlob(DOUBLE_RECORD, writer, encoded).get(FIELD_A));
-    assertEquals(42.0f, decodeGenericBlob(FLOAT_RECORD, writer, encoded).get(FIELD_A));
-    assertEquals(42L, decodeGenericBlob(LONG_RECORD, writer, encoded).get(FIELD_A));
-    assertEquals(42, decodeGenericBlob(INT_RECORD, writer, encoded).get(FIELD_A));
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    assertEquals(42.0, decodeGenericBlob(DOUBLE_RECORD, writer, encoded, encoderType).get(FIELD_A));
+    assertEquals(42.0f, decodeGenericBlob(FLOAT_RECORD, writer, encoded, encoderType).get(FIELD_A));
+    assertEquals(42L, decodeGenericBlob(LONG_RECORD, writer, encoded, encoderType).get(FIELD_A));
+    assertEquals(42, decodeGenericBlob(INT_RECORD, writer, encoded, encoderType).get(FIELD_A));
   }
 
-  @Test
-  public void asciiStringWrittenWithUnionSchemaIsConvertedToBytesSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void asciiStringWrittenWithUnionSchemaIsConvertedToBytesSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_STRING_BYTES_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, "42");
-    byte[] encoded = encodeGenericBlob(record);
-    ByteBuffer actual = (ByteBuffer) decodeGenericBlob(BYTES_RECORD, writer, encoded).get(FIELD_A);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    ByteBuffer actual = (ByteBuffer) decodeGenericBlob(BYTES_RECORD, writer, encoded, encoderType).get(FIELD_A);
     assertArrayEquals("42".getBytes(StandardCharsets.UTF_8), actual.array());
   }
 
-  @Test
-  public void utf8StringWrittenWithUnionSchemaIsConvertedToBytesSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void utf8StringWrittenWithUnionSchemaIsConvertedToBytesSchema(EncoderType encoderType) throws Exception {
     String goeran = String.format("G%sran", LATIN_SMALL_LETTER_O_WITH_DIARESIS);
     Schema writer = UNION_STRING_BYTES_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, goeran);
-    byte[] encoded = encodeGenericBlob(record);
-    ByteBuffer actual = (ByteBuffer) decodeGenericBlob(BYTES_RECORD, writer, encoded).get(FIELD_A);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    ByteBuffer actual = (ByteBuffer) decodeGenericBlob(BYTES_RECORD, writer, encoded, encoderType).get(FIELD_A);
     assertArrayEquals(goeran.getBytes(StandardCharsets.UTF_8), actual.array());
   }
 
-  @Test
-  public void asciiBytesWrittenWithUnionSchemaIsConvertedToStringSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void asciiBytesWrittenWithUnionSchemaIsConvertedToStringSchema(EncoderType encoderType) throws Exception {
     Schema writer = UNION_STRING_BYTES_RECORD;
     ByteBuffer buf = ByteBuffer.wrap("42".getBytes(StandardCharsets.UTF_8));
     Record record = defaultRecordWithSchema(writer, FIELD_A, buf);
-    byte[] encoded = encodeGenericBlob(record);
-    CharSequence read = (CharSequence) decodeGenericBlob(STRING_RECORD, writer, encoded).get(FIELD_A);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    CharSequence read = (CharSequence) decodeGenericBlob(STRING_RECORD, writer, encoded, encoderType).get(FIELD_A);
     assertEquals("42", read.toString());
   }
 
-  @Test
-  public void utf8BytesWrittenWithUnionSchemaIsConvertedToStringSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void utf8BytesWrittenWithUnionSchemaIsConvertedToStringSchema(EncoderType encoderType) throws Exception {
     String goeran = String.format("G%sran", LATIN_SMALL_LETTER_O_WITH_DIARESIS);
     Schema writer = UNION_STRING_BYTES_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, goeran);
-    byte[] encoded = encodeGenericBlob(record);
-    CharSequence read = (CharSequence) decodeGenericBlob(STRING_RECORD, writer, encoded).get(FIELD_A);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    CharSequence read = (CharSequence) decodeGenericBlob(STRING_RECORD, writer, encoded, encoderType).get(FIELD_A);
     assertEquals(goeran, read.toString());
   }
 
-  @Test
-  public void enumRecordCanBeReadWithExtendedEnumSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void enumRecordCanBeReadWithExtendedEnumSchema(EncoderType encoderType) throws Exception {
     Schema writer = ENUM_AB_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, new EnumSymbol(ENUM_AB, "A"));
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(ENUM_ABC_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(ENUM_ABC_RECORD, writer, encoded, encoderType);
     assertEquals("A", decoded.get(FIELD_A).toString());
   }
 
-  @Test
-  public void enumRecordWithExtendedSchemaCanBeReadWithOriginalEnumSchemaIfOnlyOldValues() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void enumRecordWithExtendedSchemaCanBeReadWithOriginalEnumSchemaIfOnlyOldValues(EncoderType encoderType)
+      throws Exception {
     Schema writer = ENUM_ABC_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, new EnumSymbol(ENUM_ABC, "A"));
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(ENUM_AB_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(ENUM_AB_RECORD, writer, encoded, encoderType);
     assertEquals("A", decoded.get(FIELD_A).toString());
   }
 
-  @Test
-  public void enumRecordWithExtendedSchemaCanNotBeReadIfNewValuesAreUsed() throws Exception {
-    expectedException.expect(AvroTypeException.class);
-    expectedException.expectMessage("No match for C");
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void enumRecordWithExtendedSchemaCanNotBeReadIfNewValuesAreUsed(EncoderType encoderType) throws Exception {
     Schema writer = ENUM_ABC_RECORD;
     Record record = defaultRecordWithSchema(writer, FIELD_A, new EnumSymbol(ENUM_ABC, "C"));
-    byte[] encoded = encodeGenericBlob(record);
-    decodeGenericBlob(ENUM_AB_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+
+    AvroTypeException exception = Assertions.assertThrows(AvroTypeException.class,
+        () -> decodeGenericBlob(ENUM_AB_RECORD, writer, encoded, encoderType));
+    Assertions.assertEquals("No match for C", exception.getMessage());
   }
 
-  @Test
-  public void recordWrittenWithExtendedSchemaCanBeReadWithOriginalSchemaButLossOfData() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void recordWrittenWithExtendedSchemaCanBeReadWithOriginalSchemaButLossOfData(EncoderType encoderType)
+      throws Exception {
     Schema writer = SchemaBuilder.record(RECORD_A) //
         .fields() //
         .name("newTopField").type().stringType().noDefault() //
@@ -349,47 +358,50 @@ public class TestReadingWritingDataInEvolvedSchemas {
         .endRecord();
     Record record = defaultRecordWithSchema(writer, FIELD_A, 42);
     record.put("newTopField", "not decoded");
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(INT_RECORD, writer, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(INT_RECORD, writer, encoded, encoderType);
     assertEquals(42, decoded.get(FIELD_A));
     try {
       decoded.get("newTopField");
-      Assert.fail("get should throw a exception");
+      Assertions.fail("get should throw a exception");
     } catch (AvroRuntimeException ex) {
-      Assert.assertEquals("Not a valid schema field: newTopField", ex.getMessage());
+      Assertions.assertEquals("Not a valid schema field: newTopField", ex.getMessage());
     }
   }
 
-  @Test
-  public void readerWithoutDefaultValueThrowsException() throws Exception {
-    expectedException.expect(AvroTypeException.class);
-    expectedException.expectMessage("missing required field newField");
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void readerWithoutDefaultValueThrowsException(EncoderType encoderType) throws Exception {
     Schema reader = SchemaBuilder.record(RECORD_A) //
         .fields() //
         .name("newField").type().intType().noDefault() //
         .name(FIELD_A).type().intType().noDefault() //
         .endRecord();
     Record record = defaultRecordWithSchema(INT_RECORD, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    decodeGenericBlob(reader, INT_RECORD, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    AvroTypeException exception = Assertions.assertThrows(AvroTypeException.class,
+        () -> decodeGenericBlob(reader, INT_RECORD, encoded, encoderType));
+    Assertions.assertTrue(exception.getMessage().contains("missing required field newField"), exception.getMessage());
   }
 
-  @Test
-  public void readerWithDefaultValueIsApplied() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void readerWithDefaultValueIsApplied(EncoderType encoderType) throws Exception {
     Schema reader = SchemaBuilder.record(RECORD_A) //
         .fields() //
         .name("newFieldWithDefault").type().intType().intDefault(314) //
         .name(FIELD_A).type().intType().noDefault() //
         .endRecord();
     Record record = defaultRecordWithSchema(INT_RECORD, FIELD_A, 42);
-    byte[] encoded = encodeGenericBlob(record);
-    Record decoded = decodeGenericBlob(reader, INT_RECORD, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    Record decoded = decodeGenericBlob(reader, INT_RECORD, encoded, encoderType);
     assertEquals(42, decoded.get(FIELD_A));
     assertEquals(314, decoded.get("newFieldWithDefault"));
   }
 
-  @Test
-  public void aliasesInSchema() throws Exception {
+  @ParameterizedTest
+  @EnumSource(EncoderType.class)
+  void aliasesInSchema(EncoderType encoderType) throws Exception {
     Schema writer = new Schema.Parser()
         .parse("{\"namespace\": \"example.avro\", \"type\": \"record\", \"name\": \"User\", \"fields\": ["
             + "{\"name\": \"name\", \"type\": \"int\"}\n" + "]}\n");
@@ -398,8 +410,8 @@ public class TestReadingWritingDataInEvolvedSchemas {
             + "{\"name\": \"fname\", \"type\": \"int\", \"aliases\" : [ \"name\" ]}\n" + "]}\n");
 
     GenericData.Record record = defaultRecordWithSchema(writer, "name", 1);
-    byte[] encoded = encodeGenericBlob(record);
-    GenericData.Record decoded = decodeGenericBlob(reader, reader, encoded);
+    byte[] encoded = encodeGenericBlob(record, encoderType);
+    GenericData.Record decoded = decodeGenericBlob(reader, reader, encoded, encoderType);
 
     assertEquals(1, decoded.get("fname"));
   }
@@ -410,7 +422,7 @@ public class TestReadingWritingDataInEvolvedSchemas {
     return data;
   }
 
-  private byte[] encodeGenericBlob(GenericRecord data) throws IOException {
+  private byte[] encodeGenericBlob(GenericRecord data, EncoderType encoderType) throws IOException {
     DatumWriter<GenericRecord> writer = new GenericDatumWriter<>(data.getSchema());
     ByteArrayOutputStream outStream = new ByteArrayOutputStream();
     Encoder encoder = encoderType == EncoderType.BINARY ? EncoderFactory.get().binaryEncoder(outStream, null)
@@ -421,7 +433,8 @@ public class TestReadingWritingDataInEvolvedSchemas {
     return outStream.toByteArray();
   }
 
-  private Record decodeGenericBlob(Schema expectedSchema, Schema schemaOfBlob, byte[] blob) throws IOException {
+  private Record decodeGenericBlob(Schema expectedSchema, Schema schemaOfBlob, byte[] blob, EncoderType encoderType)
+      throws IOException {
     if (blob == null) {
       return null;
     }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java
index cc5ada76e..f5e245972 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java
@@ -120,7 +120,7 @@ public class TestSchemaCompatibility {
   @Test
   void validateSchemaPairMissingField() {
     final List<Field> readerFields = list(new Schema.Field("oldfield1", INT_SCHEMA, null, null));
-    final Schema reader = Schema.createRecord(readerFields);
+    final Schema reader = Schema.createRecord(null, null, null, false, readerFields);
     final SchemaCompatibility.SchemaPairCompatibility expectedResult = new SchemaCompatibility.SchemaPairCompatibility(
         SchemaCompatibility.SchemaCompatibilityResult.compatible(), reader, WRITER_SCHEMA,
         SchemaCompatibility.READER_WRITER_COMPATIBLE_MESSAGE);
@@ -132,7 +132,7 @@ public class TestSchemaCompatibility {
   @Test
   void validateSchemaPairMissingSecondField() {
     final List<Schema.Field> readerFields = list(new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
-    final Schema reader = Schema.createRecord(readerFields);
+    final Schema reader = Schema.createRecord(null, null, null, false, readerFields);
     final SchemaCompatibility.SchemaPairCompatibility expectedResult = new SchemaCompatibility.SchemaPairCompatibility(
         SchemaCompatibility.SchemaCompatibilityResult.compatible(), reader, WRITER_SCHEMA,
         SchemaCompatibility.READER_WRITER_COMPATIBLE_MESSAGE);
@@ -145,7 +145,7 @@ public class TestSchemaCompatibility {
   void validateSchemaPairAllFields() {
     final List<Schema.Field> readerFields = list(new Schema.Field("oldfield1", INT_SCHEMA, null, null),
         new Schema.Field("oldfield2", STRING_SCHEMA, null, null));
-    final Schema reader = Schema.createRecord(readerFields);
+    final Schema reader = Schema.createRecord(null, null, null, false, readerFields);
     final SchemaCompatibility.SchemaPairCompatibility expectedResult = new SchemaCompatibility.SchemaPairCompatibility(
         SchemaCompatibility.SchemaCompatibilityResult.compatible(), reader, WRITER_SCHEMA,
         SchemaCompatibility.READER_WRITER_COMPATIBLE_MESSAGE);
@@ -158,7 +158,7 @@ public class TestSchemaCompatibility {
   void validateSchemaNewFieldWithDefault() {
     final List<Schema.Field> readerFields = list(new Schema.Field("oldfield1", INT_SCHEMA, null, null),
         new Schema.Field("newfield1", INT_SCHEMA, null, 42));
-    final Schema reader = Schema.createRecord(readerFields);
+    final Schema reader = Schema.createRecord(null, null, null, false, readerFields);
     final SchemaCompatibility.SchemaPairCompatibility expectedResult = new SchemaCompatibility.SchemaPairCompatibility(
         SchemaCompatibility.SchemaCompatibilityResult.compatible(), reader, WRITER_SCHEMA,
         SchemaCompatibility.READER_WRITER_COMPATIBLE_MESSAGE);
@@ -171,7 +171,7 @@ public class TestSchemaCompatibility {
   void validateSchemaNewField() {
     final List<Schema.Field> readerFields = list(new Schema.Field("oldfield1", INT_SCHEMA, null, null),
         new Schema.Field("newfield1", INT_SCHEMA, null, null));
-    final Schema reader = Schema.createRecord(readerFields);
+    final Schema reader = Schema.createRecord(null, null, null, false, readerFields);
     SchemaPairCompatibility compatibility = checkReaderWriterCompatibility(reader, WRITER_SCHEMA);
 
     // Test new field without default value.
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityFixedSizeMismatch.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityFixedSizeMismatch.java
index 6ac3c68dc..05321527c 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityFixedSizeMismatch.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityFixedSizeMismatch.java
@@ -17,44 +17,34 @@
  */
 package org.apache.avro;
 
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
+import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
 
-import java.util.Arrays;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import java.util.stream.Stream;
+
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.A_DINT_B_DFIXED_4_BYTES_RECORD1;
+import static org.apache.avro.TestSchemas.A_DINT_B_DFIXED_8_BYTES_RECORD1;
+import static org.apache.avro.TestSchemas.FIXED_4_BYTES;
+import static org.apache.avro.TestSchemas.FIXED_8_BYTES;
 
-@RunWith(Parameterized.class)
 public class TestSchemaCompatibilityFixedSizeMismatch {
 
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { FIXED_4_BYTES, FIXED_8_BYTES, "expected: 8, found: 4", "/size" },
-        { FIXED_8_BYTES, FIXED_4_BYTES, "expected: 4, found: 8", "/size" },
-        { A_DINT_B_DFIXED_8_BYTES_RECORD1, A_DINT_B_DFIXED_4_BYTES_RECORD1, "expected: 4, found: 8",
-            "/fields/1/type/size" },
-        { A_DINT_B_DFIXED_4_BYTES_RECORD1, A_DINT_B_DFIXED_8_BYTES_RECORD1, "expected: 8, found: 4",
-            "/fields/1/type/size" }, };
-    return Arrays.asList(fields);
+  public static Stream<Arguments> data() {
+    return Stream.of(Arguments.of(FIXED_4_BYTES, FIXED_8_BYTES, "expected: 8, found: 4", "/size"),
+        Arguments.of(FIXED_8_BYTES, FIXED_4_BYTES, "expected: 4, found: 8", "/size"),
+        Arguments.of(A_DINT_B_DFIXED_8_BYTES_RECORD1, A_DINT_B_DFIXED_4_BYTES_RECORD1, "expected: 4, found: 8",
+            "/fields/1/type/size"),
+        Arguments.of(A_DINT_B_DFIXED_4_BYTES_RECORD1, A_DINT_B_DFIXED_8_BYTES_RECORD1, "expected: 8, found: 4",
+            "/fields/1/type/size"));
   }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public String details;
-  @Parameter(3)
-  public String location;
-
-  @Test
-  public void testFixedSizeMismatchSchemas() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  void fixedSizeMismatchSchemas(Schema reader, Schema writer, String details, String location) {
     validateIncompatibleSchemas(reader, writer, SchemaIncompatibilityType.FIXED_SIZE_MISMATCH, details, location);
   }
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingEnumSymbols.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingEnumSymbols.java
index 82b70fe24..63d607cd5 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingEnumSymbols.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingEnumSymbols.java
@@ -17,19 +17,19 @@
  */
 package org.apache.avro;
 
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
+import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
 
-import java.util.Arrays;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import java.util.stream.Stream;
+
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.ENUM1_ABC_SCHEMA;
+import static org.apache.avro.TestSchemas.ENUM1_AB_SCHEMA;
+import static org.apache.avro.TestSchemas.ENUM1_BC_SCHEMA;
 
-@RunWith(Parameterized.class)
 public class TestSchemaCompatibilityMissingEnumSymbols {
 
   private static final Schema RECORD1_WITH_ENUM_AB = SchemaBuilder.record("Record1").fields() //
@@ -39,26 +39,15 @@ public class TestSchemaCompatibilityMissingEnumSymbols {
       .name("field1").type(ENUM1_ABC_SCHEMA).noDefault() //
       .endRecord();
 
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { ENUM1_AB_SCHEMA, ENUM1_ABC_SCHEMA, "[C]", "/symbols" },
-        { ENUM1_BC_SCHEMA, ENUM1_ABC_SCHEMA, "[A]", "/symbols" },
-        { RECORD1_WITH_ENUM_AB, RECORD1_WITH_ENUM_ABC, "[C]", "/fields/0/type/symbols" } };
-    return Arrays.asList(fields);
+  public static Stream<Arguments> data() {
+    return Stream.of(Arguments.of(ENUM1_AB_SCHEMA, ENUM1_ABC_SCHEMA, "[C]", "/symbols"),
+        Arguments.of(ENUM1_BC_SCHEMA, ENUM1_ABC_SCHEMA, "[A]", "/symbols"),
+        Arguments.of(RECORD1_WITH_ENUM_AB, RECORD1_WITH_ENUM_ABC, "[C]", "/fields/0/type/symbols"));
   }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public String details;
-  @Parameter(3)
-  public String location;
-
-  @Test
-  public void testTypeMismatchSchemas() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testTypeMismatchSchemas(Schema reader, Schema writer, String details, String location) {
     validateIncompatibleSchemas(reader, writer, SchemaIncompatibilityType.MISSING_ENUM_SYMBOLS, details, location);
   }
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingUnionBranch.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingUnionBranch.java
index 4f9476900..3e84a5337 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingUnionBranch.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityMissingUnionBranch.java
@@ -17,22 +17,40 @@
  */
 package org.apache.avro;
 
-import static java.util.Arrays.asList;
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(Parameterized.class)
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.A_DINT_B_DINT_STRING_UNION_RECORD1;
+import static org.apache.avro.TestSchemas.A_DINT_B_DINT_UNION_RECORD1;
+import static org.apache.avro.TestSchemas.BOOLEAN_SCHEMA;
+import static org.apache.avro.TestSchemas.BYTES_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.DOUBLE_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.ENUM1_AB_SCHEMA;
+import static org.apache.avro.TestSchemas.FIXED_4_BYTES;
+import static org.apache.avro.TestSchemas.FLOAT_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_ARRAY_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_MAP_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_STRING_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.LONG_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.NULL_SCHEMA;
+import static org.apache.avro.TestSchemas.STRING_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.list;
+
 public class TestSchemaCompatibilityMissingUnionBranch {
 
   private static final Schema RECORD1_WITH_INT = SchemaBuilder.record("Record1").fields() //
@@ -50,61 +68,52 @@ public class TestSchemaCompatibilityMissingUnionBranch {
   private static final Schema UNION_INT_MAP_INT = Schema.createUnion(list(INT_SCHEMA, INT_MAP_SCHEMA));
   private static final Schema UNION_INT_NULL = Schema.createUnion(list(INT_SCHEMA, NULL_SCHEMA));
 
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { INT_UNION_SCHEMA, INT_STRING_UNION_SCHEMA,
-            Collections.singletonList("reader union lacking writer type: STRING"), Collections.singletonList("/1") },
-        { STRING_UNION_SCHEMA, INT_STRING_UNION_SCHEMA,
-            Collections.singletonList("reader union lacking writer type: INT"), Collections.singletonList("/0") },
-        { INT_UNION_SCHEMA, UNION_INT_RECORD1, Collections.singletonList("reader union lacking writer type: RECORD"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_RECORD2, Collections.singletonList("reader union lacking writer type: RECORD"),
-            Collections.singletonList("/1") },
+  public static Stream<Arguments> data() {
+    return Stream.of( //
+        Arguments.of(INT_UNION_SCHEMA, INT_STRING_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: STRING"), Collections.singletonList("/1")),
+        Arguments.of(STRING_UNION_SCHEMA, INT_STRING_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: INT"), Collections.singletonList("/0")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_RECORD1,
+            Collections.singletonList("reader union lacking writer type: RECORD"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_RECORD2,
+            Collections.singletonList("reader union lacking writer type: RECORD"), Collections.singletonList("/1")),
         // more info in the subset schemas
-        { UNION_INT_RECORD1, UNION_INT_RECORD2, Collections.singletonList("reader union lacking writer type: RECORD"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_ENUM1_AB, Collections.singletonList("reader union lacking writer type: ENUM"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_FIXED_4_BYTES,
-            Collections.singletonList("reader union lacking writer type: FIXED"), Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_BOOLEAN, Collections.singletonList("reader union lacking writer type: BOOLEAN"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, LONG_UNION_SCHEMA, Collections.singletonList("reader union lacking writer type: LONG"),
-            Collections.singletonList("/0") },
-        { INT_UNION_SCHEMA, FLOAT_UNION_SCHEMA, Collections.singletonList("reader union lacking writer type: FLOAT"),
-            Collections.singletonList("/0") },
-        { INT_UNION_SCHEMA, DOUBLE_UNION_SCHEMA, Collections.singletonList("reader union lacking writer type: DOUBLE"),
-            Collections.singletonList("/0") },
-        { INT_UNION_SCHEMA, BYTES_UNION_SCHEMA, Collections.singletonList("reader union lacking writer type: BYTES"),
-            Collections.singletonList("/0") },
-        { INT_UNION_SCHEMA, UNION_INT_ARRAY_INT, Collections.singletonList("reader union lacking writer type: ARRAY"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_MAP_INT, Collections.singletonList("reader union lacking writer type: MAP"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, UNION_INT_NULL, Collections.singletonList("reader union lacking writer type: NULL"),
-            Collections.singletonList("/1") },
-        { INT_UNION_SCHEMA, INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA,
+        Arguments.of(UNION_INT_RECORD1, UNION_INT_RECORD2,
+            Collections.singletonList("reader union lacking writer type: RECORD"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_ENUM1_AB,
+            Collections.singletonList("reader union lacking writer type: ENUM"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_FIXED_4_BYTES,
+            Collections.singletonList("reader union lacking writer type: FIXED"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_BOOLEAN,
+            Collections.singletonList("reader union lacking writer type: BOOLEAN"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, LONG_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: LONG"), Collections.singletonList("/0")),
+        Arguments.of(INT_UNION_SCHEMA, FLOAT_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: FLOAT"), Collections.singletonList("/0")),
+        Arguments.of(INT_UNION_SCHEMA, DOUBLE_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: DOUBLE"), Collections.singletonList("/0")),
+        Arguments.of(INT_UNION_SCHEMA, BYTES_UNION_SCHEMA,
+            Collections.singletonList("reader union lacking writer type: BYTES"), Collections.singletonList("/0")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_ARRAY_INT,
+            Collections.singletonList("reader union lacking writer type: ARRAY"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_MAP_INT,
+            Collections.singletonList("reader union lacking writer type: MAP"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, UNION_INT_NULL,
+            Collections.singletonList("reader union lacking writer type: NULL"), Collections.singletonList("/1")),
+        Arguments.of(INT_UNION_SCHEMA, INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA,
             asList("reader union lacking writer type: LONG", "reader union lacking writer type: FLOAT",
                 "reader union lacking writer type: DOUBLE"),
-            asList("/1", "/2", "/3") },
-        { A_DINT_B_DINT_UNION_RECORD1, A_DINT_B_DINT_STRING_UNION_RECORD1,
+            asList("/1", "/2", "/3")),
+        Arguments.of(A_DINT_B_DINT_UNION_RECORD1, A_DINT_B_DINT_STRING_UNION_RECORD1,
             Collections.singletonList("reader union lacking writer type: STRING"),
-            Collections.singletonList("/fields/1/type/1") } };
-    return Arrays.asList(fields);
+            Collections.singletonList("/fields/1/type/1")));
   }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public List<String> details;
-  @Parameter(3)
-  public List<String> location;
-
-  @Test
-  public void testMissingUnionBranch() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testMissingUnionBranch(Schema reader, Schema writer, List<String> details, List<String> location)
+      throws Exception {
     List<SchemaIncompatibilityType> types = Collections.nCopies(details.size(),
         SchemaIncompatibilityType.MISSING_UNION_BRANCH);
     validateIncompatibleSchemas(reader, writer, types, details, location);
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityNameMismatch.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityNameMismatch.java
index 83c89ab7b..d20561faa 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityNameMismatch.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityNameMismatch.java
@@ -17,44 +17,37 @@
  */
 package org.apache.avro;
 
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
+import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
 
-import java.util.Arrays;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import java.util.stream.Stream;
+
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.A_DINT_B_DENUM_1_RECORD1;
+import static org.apache.avro.TestSchemas.A_DINT_B_DENUM_2_RECORD1;
+import static org.apache.avro.TestSchemas.EMPTY_RECORD1;
+import static org.apache.avro.TestSchemas.EMPTY_RECORD2;
+import static org.apache.avro.TestSchemas.ENUM1_AB_SCHEMA;
+import static org.apache.avro.TestSchemas.ENUM2_AB_SCHEMA;
+import static org.apache.avro.TestSchemas.FIXED_4_BYTES;
 
-@RunWith(Parameterized.class)
 public class TestSchemaCompatibilityNameMismatch {
 
   private static final Schema FIXED_4_ANOTHER_NAME = Schema.createFixed("AnotherName", null, null, 4);
 
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { ENUM1_AB_SCHEMA, ENUM2_AB_SCHEMA, "expected: Enum2", "/name" },
-        { EMPTY_RECORD2, EMPTY_RECORD1, "expected: Record1", "/name" },
-        { FIXED_4_BYTES, FIXED_4_ANOTHER_NAME, "expected: AnotherName", "/name" },
-        { A_DINT_B_DENUM_1_RECORD1, A_DINT_B_DENUM_2_RECORD1, "expected: Enum2", "/fields/1/type/name" } };
-    return Arrays.asList(fields);
+  public static Stream<Arguments> data() {
+    return Stream.of(Arguments.of(ENUM1_AB_SCHEMA, ENUM2_AB_SCHEMA, "expected: Enum2", "/name"),
+        Arguments.of(EMPTY_RECORD2, EMPTY_RECORD1, "expected: Record1", "/name"),
+        Arguments.of(FIXED_4_BYTES, FIXED_4_ANOTHER_NAME, "expected: AnotherName", "/name"),
+        Arguments.of(A_DINT_B_DENUM_1_RECORD1, A_DINT_B_DENUM_2_RECORD1, "expected: Enum2", "/fields/1/type/name"));
   }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public String details;
-  @Parameter(3)
-  public String location;
-
-  @Test
-  public void testNameMismatchSchemas() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testNameMismatchSchemas(Schema reader, Schema writer, String details, String location) throws Exception {
     validateIncompatibleSchemas(reader, writer, SchemaIncompatibilityType.NAME_MISMATCH, details, location);
   }
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityReaderFieldMissingDefaultValue.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityReaderFieldMissingDefaultValue.java
index d367caed9..7a21c1a5f 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityReaderFieldMissingDefaultValue.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityReaderFieldMissingDefaultValue.java
@@ -17,38 +17,29 @@
  */
 package org.apache.avro;
 
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
+import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
 
-import java.util.Arrays;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import java.util.stream.Stream;
+
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.A_INT_B_DINT_RECORD1;
+import static org.apache.avro.TestSchemas.A_INT_RECORD1;
+import static org.apache.avro.TestSchemas.EMPTY_RECORD1;
 
-@RunWith(Parameterized.class)
 public class TestSchemaCompatibilityReaderFieldMissingDefaultValue {
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { A_INT_RECORD1, EMPTY_RECORD1, "a", "/fields/0" }, { A_INT_B_DINT_RECORD1, EMPTY_RECORD1, "a", "/fields/0" } };
-    return Arrays.asList(fields);
-  }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public String details;
-  @Parameter(3)
-  public String location;
+  public static Stream<Arguments> data() {
+    return Stream.of(Arguments.of(A_INT_RECORD1, EMPTY_RECORD1, "a", "/fields/0"),
+        Arguments.of(A_INT_B_DINT_RECORD1, EMPTY_RECORD1, "a", "/fields/0"));
+  }
 
-  @Test
-  public void testReaderFieldMissingDefaultValueSchemas() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testReaderFieldMissingDefaultValueSchemas(Schema reader, Schema writer, String details, String location) {
     validateIncompatibleSchemas(reader, writer, SchemaIncompatibilityType.READER_FIELD_MISSING_DEFAULT_VALUE, details,
         location);
   }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityTypeMismatch.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityTypeMismatch.java
index 63dd3ac11..ba625448d 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityTypeMismatch.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibilityTypeMismatch.java
@@ -17,82 +17,94 @@
  */
 package org.apache.avro;
 
-import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
-import static org.apache.avro.TestSchemas.*;
+import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
 
-import java.util.Arrays;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.apache.avro.SchemaCompatibility.SchemaIncompatibilityType;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
+import java.util.stream.Stream;
+
+import static org.apache.avro.TestSchemaCompatibility.validateIncompatibleSchemas;
+import static org.apache.avro.TestSchemas.A_INT_RECORD1;
+import static org.apache.avro.TestSchemas.BOOLEAN_SCHEMA;
+import static org.apache.avro.TestSchemas.BYTES_SCHEMA;
+import static org.apache.avro.TestSchemas.DOUBLE_SCHEMA;
+import static org.apache.avro.TestSchemas.ENUM2_AB_SCHEMA;
+import static org.apache.avro.TestSchemas.FIXED_4_BYTES;
+import static org.apache.avro.TestSchemas.FLOAT_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_ARRAY_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_FLOAT_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_LIST_RECORD;
+import static org.apache.avro.TestSchemas.INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_MAP_SCHEMA;
+import static org.apache.avro.TestSchemas.INT_SCHEMA;
+import static org.apache.avro.TestSchemas.LONG_ARRAY_SCHEMA;
+import static org.apache.avro.TestSchemas.LONG_LIST_RECORD;
+import static org.apache.avro.TestSchemas.LONG_MAP_SCHEMA;
+import static org.apache.avro.TestSchemas.LONG_SCHEMA;
+import static org.apache.avro.TestSchemas.NULL_SCHEMA;
+import static org.apache.avro.TestSchemas.STRING_SCHEMA;
 
-@RunWith(Parameterized.class)
 public class TestSchemaCompatibilityTypeMismatch {
-  @Parameters(name = "r: {0} | w: {1}")
-  public static Iterable<Object[]> data() {
-    Object[][] fields = { //
-        { NULL_SCHEMA, INT_SCHEMA, "reader type: NULL not compatible with writer type: INT", "/" },
-        { NULL_SCHEMA, LONG_SCHEMA, "reader type: NULL not compatible with writer type: LONG", "/" },
 
-        { BOOLEAN_SCHEMA, INT_SCHEMA, "reader type: BOOLEAN not compatible with writer type: INT", "/" },
+  public static Stream<Arguments> data() {
+    return Stream.of(
+        Arguments.of(NULL_SCHEMA, INT_SCHEMA, "reader type: NULL not compatible with writer type: INT", "/"),
+        Arguments.of(NULL_SCHEMA, LONG_SCHEMA, "reader type: NULL not compatible with writer type: LONG", "/"),
+
+        Arguments.of(BOOLEAN_SCHEMA, INT_SCHEMA, "reader type: BOOLEAN not compatible with writer type: INT", "/"),
 
-        { INT_SCHEMA, NULL_SCHEMA, "reader type: INT not compatible with writer type: NULL", "/" },
-        { INT_SCHEMA, BOOLEAN_SCHEMA, "reader type: INT not compatible with writer type: BOOLEAN", "/" },
-        { INT_SCHEMA, LONG_SCHEMA, "reader type: INT not compatible with writer type: LONG", "/" },
-        { INT_SCHEMA, FLOAT_SCHEMA, "reader type: INT not compatible with writer type: FLOAT", "/" },
-        { INT_SCHEMA, DOUBLE_SCHEMA, "reader type: INT not compatible with writer type: DOUBLE", "/" },
+        Arguments.of(INT_SCHEMA, NULL_SCHEMA, "reader type: INT not compatible with writer type: NULL", "/"),
+        Arguments.of(INT_SCHEMA, BOOLEAN_SCHEMA, "reader type: INT not compatible with writer type: BOOLEAN", "/"),
+        Arguments.of(INT_SCHEMA, LONG_SCHEMA, "reader type: INT not compatible with writer type: LONG", "/"),
+        Arguments.of(INT_SCHEMA, FLOAT_SCHEMA, "reader type: INT not compatible with writer type: FLOAT", "/"),
+        Arguments.of(INT_SCHEMA, DOUBLE_SCHEMA, "reader type: INT not compatible with writer type: DOUBLE", "/"),
 
-        { LONG_SCHEMA, FLOAT_SCHEMA, "reader type: LONG not compatible with writer type: FLOAT", "/" },
-        { LONG_SCHEMA, DOUBLE_SCHEMA, "reader type: LONG not compatible with writer type: DOUBLE", "/" },
+        Arguments.of(LONG_SCHEMA, FLOAT_SCHEMA, "reader type: LONG not compatible with writer type: FLOAT", "/"),
+        Arguments.of(LONG_SCHEMA, DOUBLE_SCHEMA, "reader type: LONG not compatible with writer type: DOUBLE", "/"),
 
-        { FLOAT_SCHEMA, DOUBLE_SCHEMA, "reader type: FLOAT not compatible with writer type: DOUBLE", "/" },
+        Arguments.of(FLOAT_SCHEMA, DOUBLE_SCHEMA, "reader type: FLOAT not compatible with writer type: DOUBLE", "/"),
 
-        { DOUBLE_SCHEMA, STRING_SCHEMA, "reader type: DOUBLE not compatible with writer type: STRING", "/" },
+        Arguments.of(DOUBLE_SCHEMA, STRING_SCHEMA, "reader type: DOUBLE not compatible with writer type: STRING", "/"),
 
-        { FIXED_4_BYTES, STRING_SCHEMA, "reader type: FIXED not compatible with writer type: STRING", "/" },
+        Arguments.of(FIXED_4_BYTES, STRING_SCHEMA, "reader type: FIXED not compatible with writer type: STRING", "/"),
 
-        { STRING_SCHEMA, BOOLEAN_SCHEMA, "reader type: STRING not compatible with writer type: BOOLEAN", "/" },
-        { STRING_SCHEMA, INT_SCHEMA, "reader type: STRING not compatible with writer type: INT", "/" },
+        Arguments.of(STRING_SCHEMA, BOOLEAN_SCHEMA, "reader type: STRING not compatible with writer type: BOOLEAN",
+            "/"),
+        Arguments.of(STRING_SCHEMA, INT_SCHEMA, "reader type: STRING not compatible with writer type: INT", "/"),
 
-        { BYTES_SCHEMA, NULL_SCHEMA, "reader type: BYTES not compatible with writer type: NULL", "/" },
-        { BYTES_SCHEMA, INT_SCHEMA, "reader type: BYTES not compatible with writer type: INT", "/" },
+        Arguments.of(BYTES_SCHEMA, NULL_SCHEMA, "reader type: BYTES not compatible with writer type: NULL", "/"),
+        Arguments.of(BYTES_SCHEMA, INT_SCHEMA, "reader type: BYTES not compatible with writer type: INT", "/"),
 
-        { A_INT_RECORD1, INT_SCHEMA, "reader type: RECORD not compatible with writer type: INT", "/" },
+        Arguments.of(A_INT_RECORD1, INT_SCHEMA, "reader type: RECORD not compatible with writer type: INT", "/"),
 
-        { INT_ARRAY_SCHEMA, LONG_ARRAY_SCHEMA, "reader type: INT not compatible with writer type: LONG", "/items" },
-        { INT_MAP_SCHEMA, INT_ARRAY_SCHEMA, "reader type: MAP not compatible with writer type: ARRAY", "/" },
-        { INT_ARRAY_SCHEMA, INT_MAP_SCHEMA, "reader type: ARRAY not compatible with writer type: MAP", "/" },
-        { INT_MAP_SCHEMA, LONG_MAP_SCHEMA, "reader type: INT not compatible with writer type: LONG", "/values" },
+        Arguments.of(INT_ARRAY_SCHEMA, LONG_ARRAY_SCHEMA, "reader type: INT not compatible with writer type: LONG",
+            "/items"),
+        Arguments.of(INT_MAP_SCHEMA, INT_ARRAY_SCHEMA, "reader type: MAP not compatible with writer type: ARRAY", "/"),
+        Arguments.of(INT_ARRAY_SCHEMA, INT_MAP_SCHEMA, "reader type: ARRAY not compatible with writer type: MAP", "/"),
+        Arguments.of(INT_MAP_SCHEMA, LONG_MAP_SCHEMA, "reader type: INT not compatible with writer type: LONG",
+            "/values"),
 
-        { INT_SCHEMA, ENUM2_AB_SCHEMA, "reader type: INT not compatible with writer type: ENUM", "/" },
-        { ENUM2_AB_SCHEMA, INT_SCHEMA, "reader type: ENUM not compatible with writer type: INT", "/" },
+        Arguments.of(INT_SCHEMA, ENUM2_AB_SCHEMA, "reader type: INT not compatible with writer type: ENUM", "/"),
+        Arguments.of(ENUM2_AB_SCHEMA, INT_SCHEMA, "reader type: ENUM not compatible with writer type: INT", "/"),
 
-        { FLOAT_SCHEMA, INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA,
-            "reader type: FLOAT not compatible with writer type: DOUBLE", "/" },
-        { LONG_SCHEMA, INT_FLOAT_UNION_SCHEMA, "reader type: LONG not compatible with writer type: FLOAT", "/" },
-        { INT_SCHEMA, INT_FLOAT_UNION_SCHEMA, "reader type: INT not compatible with writer type: FLOAT", "/" },
+        Arguments.of(FLOAT_SCHEMA, INT_LONG_FLOAT_DOUBLE_UNION_SCHEMA,
+            "reader type: FLOAT not compatible with writer type: DOUBLE", "/"),
+        Arguments.of(LONG_SCHEMA, INT_FLOAT_UNION_SCHEMA, "reader type: LONG not compatible with writer type: FLOAT",
+            "/"),
+        Arguments.of(INT_SCHEMA, INT_FLOAT_UNION_SCHEMA, "reader type: INT not compatible with writer type: FLOAT",
+            "/"),
 
-        { INT_LIST_RECORD, LONG_LIST_RECORD, "reader type: INT not compatible with writer type: LONG",
-            "/fields/0/type" },
+        Arguments.of(INT_LIST_RECORD, LONG_LIST_RECORD, "reader type: INT not compatible with writer type: LONG",
+            "/fields/0/type"),
 
-        { NULL_SCHEMA, INT_SCHEMA, "reader type: NULL not compatible with writer type: INT", "/" } };
-    return Arrays.asList(fields);
+        Arguments.of(NULL_SCHEMA, INT_SCHEMA, "reader type: NULL not compatible with writer type: INT", "/"));
   }
 
-  @Parameter(0)
-  public Schema reader;
-  @Parameter(1)
-  public Schema writer;
-  @Parameter(2)
-  public String details;
-  @Parameter(3)
-  public String location;
-
-  @Test
-  public void testTypeMismatchSchemas() throws Exception {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testTypeMismatchSchemas(Schema reader, Schema writer, String details, String location) throws Exception {
     validateIncompatibleSchemas(reader, writer, SchemaIncompatibilityType.TYPE_MISMATCH, details, location);
   }
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/file/TestAllCodecs.java b/lang/java/avro/src/test/java/org/apache/avro/file/TestAllCodecs.java
index 491a7e3f7..ef928db6f 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/file/TestAllCodecs.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/file/TestAllCodecs.java
@@ -18,43 +18,27 @@
 
 package org.apache.avro.file;
 
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Collection;
+import java.util.stream.Stream;
 
-import static org.junit.Assert.assertTrue;
-
-@RunWith(Parameterized.class)
 public class TestAllCodecs {
 
-  @Parameterized.Parameters(name = "{index}: codec={0}")
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] { { "bzip2", BZip2Codec.class }, { "zstandard", ZstandardCodec.class },
-        { "null", NullCodec.class }, { "xz", XZCodec.class }, { "snappy", SnappyCodec.class },
-        { "deflate", DeflateCodec.class }, });
-  }
-
-  @Parameterized.Parameter(0)
-  public String codec;
-
-  @Parameterized.Parameter(1)
-  public Class<? extends Codec> codecClass;
-
-  @Test
-  public void testCodec() throws IOException {
+  @ParameterizedTest
+  @MethodSource("codecTypes")
+  void codec(String codec, Class<? extends Codec> codecClass) throws IOException {
     int inputSize = 500_000;
 
     byte[] input = generateTestData(inputSize);
 
     Codec codecInstance = CodecFactory.fromString(codec).createInstance();
-    assertTrue(codecClass.isInstance(codecInstance));
-    assertTrue(codecInstance.getName().equals(codec));
+    Assertions.assertTrue(codecClass.isInstance(codecInstance));
+    Assertions.assertTrue(codecInstance.getName().equals(codec));
 
     ByteBuffer inputByteBuffer = ByteBuffer.wrap(input);
     ByteBuffer compressedBuffer = codecInstance.compress(inputByteBuffer);
@@ -62,28 +46,30 @@ public class TestAllCodecs {
     int compressedSize = compressedBuffer.remaining();
 
     // Make sure something returned
-    assertTrue(compressedSize > 0);
+    Assertions.assertTrue(compressedSize > 0);
 
     // While the compressed size could in many real cases
     // *increase* compared to the input size, our input data
     // is extremely easy to compress and all Avro's compression algorithms
     // should have a compression ratio greater than 1 (except 'null').
-    assertTrue(compressedSize < inputSize || codec.equals("null"));
+    Assertions.assertTrue(compressedSize < inputSize || codec.equals("null"));
 
     // Decompress the data
     ByteBuffer decompressedBuffer = codecInstance.decompress(compressedBuffer);
 
     // Validate the the input and output are equal.
     inputByteBuffer.rewind();
-    Assert.assertEquals(decompressedBuffer, inputByteBuffer);
+    Assertions.assertEquals(inputByteBuffer, decompressedBuffer);
   }
 
-  @Test
-  public void testCodecSlice() throws IOException {
+  @ParameterizedTest
+  @MethodSource("codecTypes")
+  void codecSlice(String codec, Class<? extends Codec> codecClass) throws IOException {
     int inputSize = 500_000;
     byte[] input = generateTestData(inputSize);
 
     Codec codecInstance = CodecFactory.fromString(codec).createInstance();
+    Assertions.assertTrue(codecClass.isInstance(codecInstance));
 
     ByteBuffer partialBuffer = ByteBuffer.wrap(input);
     partialBuffer.position(17);
@@ -94,7 +80,7 @@ public class TestAllCodecs {
     int compressedSize = compressedBuffer.remaining();
 
     // Make sure something returned
-    assertTrue(compressedSize > 0);
+    Assertions.assertTrue(compressedSize > 0);
 
     // Create a slice from the compressed buffer
     ByteBuffer sliceBuffer = ByteBuffer.allocate(compressedSize + 100);
@@ -108,7 +94,13 @@ public class TestAllCodecs {
 
     // Validate the the input and output are equal.
     inputByteBuffer.rewind();
-    Assert.assertEquals(decompressedBuffer, inputByteBuffer);
+    Assertions.assertEquals(inputByteBuffer, decompressedBuffer);
+  }
+
+  public static Stream<Arguments> codecTypes() {
+    return Stream.of(Arguments.of("bzip2", BZip2Codec.class), Arguments.of("zstandard", ZstandardCodec.class),
+        Arguments.of("null", NullCodec.class), Arguments.of("xz", XZCodec.class),
+        Arguments.of("snappy", SnappyCodec.class), Arguments.of("deflate", DeflateCodec.class));
   }
 
   // Generate some test data that will compress easily
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java
index fe405cfb9..81fe27d45 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java
@@ -17,15 +17,6 @@
  */
 package org.apache.avro.io;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import org.apache.avro.AvroRuntimeException;
 import org.apache.avro.Schema;
 import org.apache.avro.generic.GenericDatumReader;
@@ -34,39 +25,38 @@ import org.apache.avro.util.ByteBufferInputStream;
 import org.apache.avro.util.ByteBufferOutputStream;
 import org.apache.avro.util.RandomData;
 import org.apache.avro.util.Utf8;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
 public class TestBinaryDecoder {
   // prime number buffer size so that looping tests hit the buffer edge
   // at different points in the loop.
   DecoderFactory factory = new DecoderFactory().configureDecoderBufferSize(521);
-  private boolean useDirect = false;
-  static EncoderFactory e_factory = EncoderFactory.get();
 
-  public TestBinaryDecoder(boolean useDirect) {
-    this.useDirect = useDirect;
-  }
-
-  @Parameters
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] { { true }, { false }, });
-  }
+  static EncoderFactory e_factory = EncoderFactory.get();
 
-  private Decoder newDecoderWithNoData() {
-    return newDecoder(new byte[0]);
+  private Decoder newDecoderWithNoData(boolean useDirect) {
+    return newDecoder(new byte[0], useDirect);
   }
 
-  private BinaryDecoder newDecoder(byte[] bytes, int start, int len) {
-    return this.newDecoder(bytes, start, len, null);
+  private BinaryDecoder newDecoder(byte[] bytes, int start, int len, boolean useDirect) {
+    return this.newDecoder(bytes, start, len, null, useDirect);
   }
 
-  private BinaryDecoder newDecoder(byte[] bytes, int start, int len, BinaryDecoder reuse) {
+  private BinaryDecoder newDecoder(byte[] bytes, int start, int len, BinaryDecoder reuse, boolean useDirect) {
     if (useDirect) {
       final ByteArrayInputStream input = new ByteArrayInputStream(bytes, start, len);
       return factory.directBinaryDecoder(input, reuse);
@@ -75,11 +65,11 @@ public class TestBinaryDecoder {
     }
   }
 
-  private BinaryDecoder newDecoder(InputStream in) {
-    return this.newDecoder(in, null);
+  private BinaryDecoder newDecoder(InputStream in, boolean useDirect) {
+    return this.newDecoder(in, null, useDirect);
   }
 
-  private BinaryDecoder newDecoder(InputStream in, BinaryDecoder reuse) {
+  private BinaryDecoder newDecoder(InputStream in, BinaryDecoder reuse, boolean useDirect) {
     if (useDirect) {
       return factory.directBinaryDecoder(in, reuse);
     } else {
@@ -87,67 +77,76 @@ public class TestBinaryDecoder {
     }
   }
 
-  private BinaryDecoder newDecoder(byte[] bytes, BinaryDecoder reuse) {
-    if (this.useDirect) {
+  private BinaryDecoder newDecoder(byte[] bytes, BinaryDecoder reuse, boolean useDirect) {
+    if (useDirect) {
       return this.factory.directBinaryDecoder(new ByteArrayInputStream(bytes), reuse);
     } else {
       return factory.binaryDecoder(bytes, reuse);
     }
   }
 
-  private BinaryDecoder newDecoder(byte[] bytes) {
-    return this.newDecoder(bytes, null);
+  private BinaryDecoder newDecoder(byte[] bytes, boolean useDirect) {
+    return this.newDecoder(bytes, null, useDirect);
   }
 
   /** Verify EOFException throw at EOF */
 
-  @Test(expected = EOFException.class)
-  public void testEOFBoolean() throws IOException {
-    newDecoderWithNoData().readBoolean();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofBoolean(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readBoolean());
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFInt() throws IOException {
-    newDecoderWithNoData().readInt();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofInt(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readInt());
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFLong() throws IOException {
-    newDecoderWithNoData().readLong();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofLong(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readLong());
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFFloat() throws IOException {
-    newDecoderWithNoData().readFloat();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofFloat(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readFloat());
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFDouble() throws IOException {
-    newDecoderWithNoData().readDouble();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofDouble(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readDouble());
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFBytes() throws IOException {
-    newDecoderWithNoData().readBytes(null);
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofBytes(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readBytes(null));
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFString() throws IOException {
-    newDecoderWithNoData().readString(new Utf8("a"));
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofString(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readString(new Utf8("a")));
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFFixed() throws IOException {
-    newDecoderWithNoData().readFixed(new byte[1]);
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofFixed(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readFixed(new byte[1]));
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOFEnum() throws IOException {
-    newDecoderWithNoData().readEnum();
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eofEnum(boolean useDirect) {
+    Assertions.assertThrows(EOFException.class, () -> newDecoderWithNoData(useDirect).readEnum());
   }
 
   @Test
-  public void testReuse() throws IOException {
+  void reuse() throws IOException {
     ByteBufferOutputStream bbo1 = new ByteBufferOutputStream();
     ByteBufferOutputStream bbo2 = new ByteBufferOutputStream();
     byte[] b1 = new byte[] { 1, 2 };
@@ -162,11 +161,11 @@ public class TestBinaryDecoder {
 
     DirectBinaryDecoder d = new DirectBinaryDecoder(new ByteBufferInputStream(bbo1.getBufferList()));
     ByteBuffer bb1 = d.readBytes(null);
-    Assert.assertEquals(b1.length, bb1.limit() - bb1.position());
+    Assertions.assertEquals(b1.length, bb1.limit() - bb1.position());
 
     d.configure(new ByteBufferInputStream(bbo2.getBufferList()));
     ByteBuffer bb2 = d.readBytes(null);
-    Assert.assertEquals(b1.length, bb2.limit() - bb2.position());
+    Assertions.assertEquals(b1.length, bb2.limit() - bb2.position());
 
   }
 
@@ -175,7 +174,7 @@ public class TestBinaryDecoder {
   private static final int count = 200;
   private static final ArrayList<Object> records = new ArrayList<>(count);
 
-  @BeforeClass
+  @BeforeAll
   public static void generateData() throws IOException {
     int seed = (int) System.currentTimeMillis();
     // note some tests (testSkipping) rely on this explicitly
@@ -199,8 +198,9 @@ public class TestBinaryDecoder {
     data = baos.toByteArray();
   }
 
-  @Test
-  public void testDecodeFromSources() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void decodeFromSources(boolean useDirect) throws IOException {
     GenericDatumReader<Object> reader = new GenericDatumReader<>();
     reader.setSchema(schema);
 
@@ -208,81 +208,82 @@ public class TestBinaryDecoder {
     ByteArrayInputStream is2 = new ByteArrayInputStream(data);
     ByteArrayInputStream is3 = new ByteArrayInputStream(data);
 
-    Decoder fromInputStream = newDecoder(is);
-    Decoder fromArray = newDecoder(data);
+    Decoder fromInputStream = newDecoder(is, useDirect);
+    Decoder fromArray = newDecoder(data, useDirect);
 
     byte[] data2 = new byte[data.length + 30];
     Arrays.fill(data2, (byte) 0xff);
     System.arraycopy(data, 0, data2, 15, data.length);
 
-    Decoder fromOffsetArray = newDecoder(data2, 15, data.length);
+    Decoder fromOffsetArray = newDecoder(data2, 15, data.length, useDirect);
 
-    BinaryDecoder initOnInputStream = newDecoder(new byte[50], 0, 30);
-    initOnInputStream = newDecoder(is2, initOnInputStream);
-    BinaryDecoder initOnArray = this.newDecoder(is3, null);
-    initOnArray = this.newDecoder(data, initOnArray);
+    BinaryDecoder initOnInputStream = newDecoder(new byte[50], 0, 30, useDirect);
+    initOnInputStream = newDecoder(is2, initOnInputStream, useDirect);
+    BinaryDecoder initOnArray = this.newDecoder(is3, null, useDirect);
+    initOnArray = this.newDecoder(data, initOnArray, useDirect);
 
     for (Object datum : records) {
-      Assert.assertEquals("InputStream based BinaryDecoder result does not match", datum,
-          reader.read(null, fromInputStream));
-      Assert.assertEquals("Array based BinaryDecoder result does not match", datum, reader.read(null, fromArray));
-      Assert.assertEquals("offset Array based BinaryDecoder result does not match", datum,
-          reader.read(null, fromOffsetArray));
-      Assert.assertEquals("InputStream initialized BinaryDecoder result does not match", datum,
-          reader.read(null, initOnInputStream));
-      Assert.assertEquals("Array initialized BinaryDecoder result does not match", datum,
-          reader.read(null, initOnArray));
+      Assertions.assertEquals(datum, reader.read(null, fromInputStream),
+          "InputStream based BinaryDecoder result does not match");
+      Assertions.assertEquals(datum, reader.read(null, fromArray), "Array based BinaryDecoder result does not match");
+      Assertions.assertEquals(datum, reader.read(null, fromOffsetArray),
+          "offset Array based BinaryDecoder result does not match");
+      Assertions.assertEquals(datum, reader.read(null, initOnInputStream),
+          "InputStream initialized BinaryDecoder result does not match");
+      Assertions.assertEquals(datum, reader.read(null, initOnArray),
+          "Array initialized BinaryDecoder result does not match");
     }
   }
 
-  @Test
-  public void testInputStreamProxy() throws IOException {
-    BinaryDecoder d = newDecoder(data);
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void inputStreamProxy(boolean useDirect) throws IOException {
+    BinaryDecoder d = newDecoder(data, useDirect);
     if (d != null) {
       BinaryDecoder bd = d;
       InputStream test = bd.inputStream();
       InputStream check = new ByteArrayInputStream(data);
       validateInputStreamReads(test, check);
-      bd = this.newDecoder(data, bd);
+      bd = this.newDecoder(data, bd, useDirect);
       test = bd.inputStream();
       check = new ByteArrayInputStream(data);
       validateInputStreamSkips(test, check);
       // with input stream sources
-      bd = newDecoder(new ByteArrayInputStream(data), bd);
+      bd = newDecoder(new ByteArrayInputStream(data), bd, useDirect);
       test = bd.inputStream();
       check = new ByteArrayInputStream(data);
       validateInputStreamReads(test, check);
-      bd = newDecoder(new ByteArrayInputStream(data), bd);
+      bd = newDecoder(new ByteArrayInputStream(data), bd, useDirect);
       test = bd.inputStream();
       check = new ByteArrayInputStream(data);
       validateInputStreamSkips(test, check);
     }
   }
 
-  @Test
-  public void testInputStreamProxyDetached() throws IOException {
-    Decoder d = newDecoder(data);
-    if (d instanceof BinaryDecoder) {
-      BinaryDecoder bd = (BinaryDecoder) d;
-      InputStream test = bd.inputStream();
-      InputStream check = new ByteArrayInputStream(data);
-      // detach input stream and decoder from old source
-      this.newDecoder(new byte[56]);
-      try (InputStream bad = bd.inputStream(); InputStream check2 = new ByteArrayInputStream(data)) {
-        validateInputStreamReads(test, check);
-        Assert.assertNotEquals(bad.read(), check2.read());
-      }
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void inputStreamProxyDetached(boolean useDirect) throws IOException {
+    BinaryDecoder bd = newDecoder(data, useDirect);
+
+    InputStream test = bd.inputStream();
+    InputStream check = new ByteArrayInputStream(data);
+    // detach input stream and decoder from old source
+    this.newDecoder(new byte[56], useDirect);
+    try (InputStream bad = bd.inputStream(); InputStream check2 = new ByteArrayInputStream(data)) {
+      validateInputStreamReads(test, check);
+      Assertions.assertNotEquals(bad.read(), check2.read());
     }
   }
 
-  @Test
-  public void testInputStreamPartiallyUsed() throws IOException {
-    BinaryDecoder bd = this.newDecoder(new ByteArrayInputStream(data));
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void inputStreamPartiallyUsed(boolean useDirect) throws IOException {
+    BinaryDecoder bd = this.newDecoder(new ByteArrayInputStream(data), useDirect);
     InputStream test = bd.inputStream();
     InputStream check = new ByteArrayInputStream(data);
     // triggers buffer fill if unused and tests isEnd()
     try {
-      Assert.assertFalse(bd.isEnd());
+      Assertions.assertFalse(bd.isEnd());
     } catch (UnsupportedOperationException e) {
       // this is ok if its a DirectBinaryDecoder.
       if (bd.getClass() != DirectBinaryDecoder.class) {
@@ -300,25 +301,28 @@ public class TestBinaryDecoder {
     while (true) {
       int t = test.read();
       int c = check.read();
-      Assert.assertEquals(c, t);
-      if (-1 == t)
+      Assertions.assertEquals(c, t);
+      if (-1 == t) {
         break;
+      }
       t = test.read(bt);
       c = check.read(bc);
-      Assert.assertEquals(c, t);
-      Assert.assertArrayEquals(bt, bc);
-      if (-1 == t)
+      Assertions.assertEquals(c, t);
+      Assertions.assertArrayEquals(bt, bc);
+      if (-1 == t) {
         break;
+      }
       t = test.read(bt, 1, 4);
       c = check.read(bc, 1, 4);
-      Assert.assertEquals(c, t);
-      Assert.assertArrayEquals(bt, bc);
-      if (-1 == t)
+      Assertions.assertEquals(c, t);
+      Assertions.assertArrayEquals(bt, bc);
+      if (-1 == t) {
         break;
+      }
     }
-    Assert.assertEquals(0, test.skip(5));
-    Assert.assertEquals(0, test.available());
-    Assert.assertFalse(test.getClass() != ByteArrayInputStream.class && test.markSupported());
+    Assertions.assertEquals(0, test.skip(5));
+    Assertions.assertEquals(0, test.available());
+    Assertions.assertFalse(test.getClass() != ByteArrayInputStream.class && test.markSupported());
     test.close();
   }
 
@@ -326,154 +330,168 @@ public class TestBinaryDecoder {
     while (true) {
       long t2 = test.skip(19);
       long c2 = check.skip(19);
-      Assert.assertEquals(c2, t2);
-      if (0 == t2)
+      Assertions.assertEquals(c2, t2);
+      if (0 == t2) {
         break;
+      }
     }
-    Assert.assertEquals(-1, test.read());
+    Assertions.assertEquals(-1, test.read());
   }
 
-  @Test
-  public void testBadIntEncoding() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void badIntEncoding(boolean useDirect) throws IOException {
     byte[] badint = new byte[5];
     Arrays.fill(badint, (byte) 0xff);
-    Decoder bd = this.newDecoder(badint);
+    Decoder bd = this.newDecoder(badint, useDirect);
     String message = "";
     try {
       bd.readInt();
     } catch (IOException ioe) {
       message = ioe.getMessage();
     }
-    Assert.assertEquals("Invalid int encoding", message);
+    Assertions.assertEquals("Invalid int encoding", message);
   }
 
-  @Test
-  public void testBadLongEncoding() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void badLongEncoding(boolean useDirect) throws IOException {
     byte[] badint = new byte[10];
     Arrays.fill(badint, (byte) 0xff);
-    Decoder bd = this.newDecoder(badint);
+    Decoder bd = this.newDecoder(badint, useDirect);
     String message = "";
     try {
       bd.readLong();
     } catch (IOException ioe) {
       message = ioe.getMessage();
     }
-    Assert.assertEquals("Invalid long encoding", message);
+    Assertions.assertEquals("Invalid long encoding", message);
   }
 
-  @Test
-  public void testNegativeStringLength() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void negativeStringLength(boolean useDirect) throws IOException {
     byte[] bad = new byte[] { (byte) 1 };
-    Decoder bd = this.newDecoder(bad);
+    Decoder bd = this.newDecoder(bad, useDirect);
 
-    Assert.assertThrows("Malformed data. Length is negative: -1", AvroRuntimeException.class, bd::readString);
+    Assertions.assertThrows(AvroRuntimeException.class, bd::readString, "Malformed data. Length is negative: -1");
   }
 
-  @Test
-  public void testStringMaxArraySize() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void stringMaxArraySize(boolean useDirect) {
     byte[] bad = new byte[10];
     BinaryData.encodeLong(BinaryDecoder.MAX_ARRAY_SIZE + 1, bad, 0);
-    Decoder bd = this.newDecoder(bad);
+    Decoder bd = this.newDecoder(bad, useDirect);
 
-    Assert.assertThrows("Cannot read strings longer than " + BinaryDecoder.MAX_ARRAY_SIZE + " bytes",
-        UnsupportedOperationException.class, bd::readString);
+    Assertions.assertThrows(UnsupportedOperationException.class, bd::readString,
+        "Cannot read strings longer than " + BinaryDecoder.MAX_ARRAY_SIZE + " bytes");
   }
 
-  @Test
-  public void testNegativeBytesLength() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void negativeBytesLength(boolean useDirect) {
     byte[] bad = new byte[] { (byte) 1 };
-    Decoder bd = this.newDecoder(bad);
+    Decoder bd = this.newDecoder(bad, useDirect);
 
-    Assert.assertThrows("Malformed data. Length is negative: -1", AvroRuntimeException.class, () -> bd.readBytes(null));
+    Assertions.assertThrows(AvroRuntimeException.class, () -> bd.readBytes(null),
+        "Malformed data. Length is negative: -1");
   }
 
-  @Test
-  public void testBytesMaxArraySize() {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void bytesMaxArraySize(boolean useDirect) {
     byte[] bad = new byte[10];
     BinaryData.encodeLong(BinaryDecoder.MAX_ARRAY_SIZE + 1, bad, 0);
-    Decoder bd = this.newDecoder(bad);
+    Decoder bd = this.newDecoder(bad, useDirect);
 
-    Assert.assertThrows("Cannot read arrays longer than " + BinaryDecoder.MAX_ARRAY_SIZE + " bytes",
-        UnsupportedOperationException.class, () -> bd.readBytes(null));
+    Assertions.assertThrows(UnsupportedOperationException.class, () -> bd.readBytes(null),
+        "Cannot read arrays longer than " + BinaryDecoder.MAX_ARRAY_SIZE + " bytes");
   }
 
-  @Test
-  public void testBytesMaxLengthProperty() {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void bytesMaxLengthProperty(boolean useDirect) {
     int maxLength = 128;
     byte[] bad = new byte[10];
     BinaryData.encodeLong(maxLength + 1, bad, 0);
     try {
       System.setProperty("org.apache.avro.limits.bytes.maxLength", Long.toString(maxLength));
-      Decoder bd = this.newDecoder(bad);
+      Decoder bd = this.newDecoder(bad, useDirect);
 
-      Assert.assertThrows("Bytes length " + (maxLength + 1) + " exceeds maximum allowed", AvroRuntimeException.class,
-          () -> bd.readBytes(null));
+      Assertions.assertThrows(AvroRuntimeException.class, () -> bd.readBytes(null),
+          "Bytes length " + (maxLength + 1) + " exceeds maximum allowed");
     } finally {
       System.clearProperty("org.apache.avro.limits.bytes.maxLength");
     }
   }
 
-  @Test(expected = UnsupportedOperationException.class)
-  public void testLongLengthEncoding() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void longLengthEncoding(boolean useDirect) {
     // Size equivalent to Integer.MAX_VALUE + 1
     byte[] bad = new byte[] { (byte) -128, (byte) -128, (byte) -128, (byte) -128, (byte) 16 };
-    Decoder bd = this.newDecoder(bad);
-    bd.readString();
+    Decoder bd = this.newDecoder(bad, useDirect);
+    Assertions.assertThrows(UnsupportedOperationException.class, bd::readString);
   }
 
-  @Test(expected = EOFException.class)
-  public void testIntTooShort() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void intTooShort(boolean useDirect) {
     byte[] badint = new byte[4];
     Arrays.fill(badint, (byte) 0xff);
-    newDecoder(badint).readInt();
+    Assertions.assertThrows(EOFException.class, () -> newDecoder(badint, useDirect).readInt());
   }
 
-  @Test(expected = EOFException.class)
-  public void testLongTooShort() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void longTooShort(boolean useDirect) {
     byte[] badint = new byte[9];
     Arrays.fill(badint, (byte) 0xff);
-    newDecoder(badint).readLong();
+    Assertions.assertThrows(EOFException.class, () -> newDecoder(badint, useDirect).readLong());
   }
 
-  @Test(expected = EOFException.class)
-  public void testFloatTooShort() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void floatTooShort(boolean useDirect) {
     byte[] badint = new byte[3];
     Arrays.fill(badint, (byte) 0xff);
-    newDecoder(badint).readInt();
+    Assertions.assertThrows(EOFException.class, () -> newDecoder(badint, useDirect).readInt());
   }
 
-  @Test(expected = EOFException.class)
-  public void testDoubleTooShort() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void doubleTooShort(boolean useDirect) {
     byte[] badint = new byte[7];
     Arrays.fill(badint, (byte) 0xff);
-    newDecoder(badint).readLong();
+    Assertions.assertThrows(EOFException.class, () -> newDecoder(badint, useDirect).readLong());
   }
 
-  @Test
-  public void testSkipping() throws IOException {
-    Decoder d = newDecoder(data);
-    skipGenerated(d);
-    if (d instanceof BinaryDecoder) {
-      BinaryDecoder bd = (BinaryDecoder) d;
-      try {
-        Assert.assertTrue(bd.isEnd());
-      } catch (UnsupportedOperationException e) {
-        // this is ok if its a DirectBinaryDecoder.
-        if (bd.getClass() != DirectBinaryDecoder.class) {
-          throw e;
-        }
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void skipping(boolean useDirect) throws IOException {
+    BinaryDecoder bd = newDecoder(data, useDirect);
+    skipGenerated(bd);
+
+    try {
+      Assertions.assertTrue(bd.isEnd());
+    } catch (UnsupportedOperationException e) {
+      // this is ok if its a DirectBinaryDecoder.
+      if (bd.getClass() != DirectBinaryDecoder.class) {
+        throw e;
       }
-      bd = this.newDecoder(new ByteArrayInputStream(data), bd);
-      skipGenerated(bd);
-      try {
-        Assert.assertTrue(bd.isEnd());
-      } catch (UnsupportedOperationException e) {
-        // this is ok if its a DirectBinaryDecoder.
-        if (bd.getClass() != DirectBinaryDecoder.class) {
-          throw e;
-        }
+    }
+    bd = this.newDecoder(new ByteArrayInputStream(data), bd, useDirect);
+    skipGenerated(bd);
+    try {
+      Assertions.assertTrue(bd.isEnd());
+    } catch (UnsupportedOperationException e) {
+      // this is ok if its a DirectBinaryDecoder.
+      if (bd.getClass() != DirectBinaryDecoder.class) {
+        throw e;
       }
     }
+
   }
 
   private void skipGenerated(Decoder bd) throws IOException {
@@ -496,19 +514,20 @@ public class TestBinaryDecoder {
     } catch (EOFException e) {
       eof = e;
     }
-    Assert.assertNotNull(eof);
+    Assertions.assertNotNull(eof);
   }
 
-  @Test(expected = EOFException.class)
-  public void testEOF() throws IOException {
+  @ParameterizedTest
+  @ValueSource(booleans = { true, false })
+  void eof(boolean useDirect) throws IOException {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     Encoder e = EncoderFactory.get().binaryEncoder(baos, null);
     e.writeLong(0x10000000000000L);
     e.flush();
 
-    Decoder d = newDecoder(new ByteArrayInputStream(baos.toByteArray()));
-    Assert.assertEquals(0x10000000000000L, d.readLong());
-    d.readInt();
+    Decoder d = newDecoder(new ByteArrayInputStream(baos.toByteArray()), useDirect);
+    Assertions.assertEquals(0x10000000000000L, d.readLong());
+    Assertions.assertThrows(EOFException.class, () -> d.readInt());
   }
 
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO.java
index 6beda2ae6..d107b9d82 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO.java
@@ -17,7 +17,12 @@
  */
 package org.apache.avro.io;
 
-import static org.junit.Assert.*;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -25,28 +30,14 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Collection;
+import java.util.stream.Stream;
 
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonParser;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@RunWith(Parameterized.class)
 public class TestBlockingIO {
 
-  private final int iSize;
-  private final int iDepth;
-  private final String sInput;
-
-  public TestBlockingIO(int sz, int dp, String inp) {
-    this.iSize = sz;
-    this.iDepth = dp;
-    this.sInput = inp;
-  }
-
   private static class Tests {
     private final JsonParser parser;
     private final Decoder input;
@@ -206,25 +197,29 @@ public class TestBlockingIO {
     }
   }
 
-  @Test
-  public void testScan() throws IOException {
-    Tests t = new Tests(iSize, iDepth, sInput);
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testScan(int size, int depth, String input) throws IOException {
+    Tests t = new Tests(size, depth, input);
     t.scan();
   }
 
-  @Test
-  public void testSkip1() throws IOException {
-    testSkip(iSize, iDepth, sInput, 0);
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testSkip1(int size, int depth, String input) throws IOException {
+    testSkip(size, depth, input, 0);
   }
 
-  @Test
-  public void testSkip2() throws IOException {
-    testSkip(iSize, iDepth, sInput, 1);
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testSkip2(int size, int depth, String input) throws IOException {
+    testSkip(size, depth, input, 1);
   }
 
-  @Test
-  public void testSkip3() throws IOException {
-    testSkip(iSize, iDepth, sInput, 2);
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testSkip3(int size, int depth, String input) throws IOException {
+    testSkip(size, depth, input, 2);
   }
 
   private void testSkip(int bufferSize, int depth, String input, int skipLevel) throws IOException {
@@ -323,9 +318,8 @@ public class TestBlockingIO {
     }
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] { { 64, 0, "" }, { 64, 0, jss(0, 'a') }, { 64, 0, jss(3, 'a') },
+  public static Stream<Arguments> data() {
+    return Stream.of(new Object[][] { { 64, 0, "" }, { 64, 0, jss(0, 'a') }, { 64, 0, jss(3, 'a') },
         { 64, 0, jss(64, 'a') }, { 64, 0, jss(65, 'a') }, { 64, 0, jss(100, 'a') }, { 64, 1, "[]" },
         { 64, 1, "[" + jss(0, 'a') + "]" }, { 64, 1, "[" + jss(3, 'a') + "]" }, { 64, 1, "[" + jss(61, 'a') + "]" },
         { 64, 1, "[" + jss(62, 'a') + "]" }, { 64, 1, "[" + jss(64, 'a') + "]" }, { 64, 1, "[" + jss(65, 'a') + "]" },
@@ -387,7 +381,8 @@ public class TestBlockingIO {
         { 100, 2, "[[\"pqr\", \"ab\", \"mnopqrstuvwx\"]]" }, { 64, 2, "[[[\"pqr\"]], [[\"ab\"], [\"mnopqrstuvwx\"]]]" },
 
         { 64, 1, "{}" }, { 64, 1, "{\"n\": \"v\"}" }, { 64, 1, "{\"n1\": \"v\", \"n2\": []}" },
-        { 100, 1, "{\"n1\": \"v\", \"n2\": []}" }, { 100, 1, "{\"n1\": \"v\", \"n2\": [\"abc\"]}" }, });
+        { 100, 1, "{\"n1\": \"v\", \"n2\": []}" }, { 100, 1, "{\"n1\": \"v\", \"n2\": [\"abc\"]}" }, })
+        .map(Arguments::of);
   }
 
   /**
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO2.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO2.java
index 3a91bb96d..378e17ee6 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO2.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestBlockingIO2.java
@@ -17,14 +17,13 @@
  */
 package org.apache.avro.io;
 
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import java.util.stream.Stream;
 
 /**
  * This class has more exhaustive tests for Blocking IO. The reason we have both
@@ -32,38 +31,29 @@ import org.junit.runners.Parameterized;
  * TestBlockingIO2, it is hard to test skip() operations. and with the test
  * infrastructure of TestBlockingIO, it is hard to test enums, unions etc.
  */
-@RunWith(Parameterized.class)
 public class TestBlockingIO2 {
-  private final Decoder decoder;
-  private final String calls;
-  private Object[] values;
-  private String msg;
-
-  public TestBlockingIO2(int bufferSize, int skipLevel, String calls) throws IOException {
 
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testScan(int bufferSize, int skipLevel, String calls) throws IOException {
     ByteArrayOutputStream os = new ByteArrayOutputStream();
     EncoderFactory factory = new EncoderFactory().configureBlockSize(bufferSize);
     Encoder encoder = factory.blockingBinaryEncoder(os, null);
-    this.values = TestValidatingIO.randomValues(calls);
+    Object[] values = TestValidatingIO.randomValues(calls);
 
     TestValidatingIO.generate(encoder, calls, values);
     encoder.flush();
 
     byte[] bb = os.toByteArray();
 
-    decoder = DecoderFactory.get().binaryDecoder(bb, null);
-    this.calls = calls;
-    this.msg = "Case: { " + bufferSize + ", " + skipLevel + ", \"" + calls + "\" }";
-  }
+    Decoder decoder = DecoderFactory.get().binaryDecoder(bb, null);
+    String msg = "Case: { " + bufferSize + ", " + skipLevel + ", \"" + calls + "\" }";
 
-  @Test
-  public void testScan() throws IOException {
     TestValidatingIO.check(msg, decoder, calls, values, -1);
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] { { 64, 0, "" }, { 64, 0, "S0" }, { 64, 0, "S3" }, { 64, 0, "S64" },
+  public static Stream<Arguments> data() {
+    return Stream.of(new Object[][] { { 64, 0, "" }, { 64, 0, "S0" }, { 64, 0, "S3" }, { 64, 0, "S64" },
         { 64, 0, "S65" }, { 64, 0, "S100" }, { 64, 1, "[]" }, { 64, 1, "[c1sS0]" }, { 64, 1, "[c1sS3]" },
         { 64, 1, "[c1sS61]" }, { 64, 1, "[c1sS62]" }, { 64, 1, "[c1sS64]" }, { 64, 1, "[c1sS65]" },
         { 64, 1, "[c2sS0sS0]" }, { 64, 1, "[c2sS0sS10]" }, { 64, 1, "[c2sS0sS63]" }, { 64, 1, "[c2sS0sS64]" },
@@ -99,6 +89,6 @@ public class TestBlockingIO2 {
 
         { 100, 1, "{c1sK5e10}" }, { 100, 1, "{c1sK5U1S10}" }, { 100, 1, "{c1sK5f10S10}" }, { 100, 1, "{c1sK5NS10}" },
         { 100, 1, "{c1sK5BS10}" }, { 100, 1, "{c1sK5IS10}" }, { 100, 1, "{c1sK5LS10}" }, { 100, 1, "{c1sK5FS10}" },
-        { 100, 1, "{c1sK5DS10}" }, });
+        { 100, 1, "{c1sK5DS10}" }, }).map(Arguments::of);
   }
 }
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIO.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIO.java
index c880d9fd5..8a9604279 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIO.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIO.java
@@ -17,48 +17,34 @@
  */
 package org.apache.avro.io;
 
+import org.apache.avro.Schema;
+import org.apache.avro.io.TestValidatingIO.Encoding;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collection;
+import java.util.stream.Stream;
 
-import org.apache.avro.Schema;
-import org.apache.avro.io.TestValidatingIO.Encoding;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
 public class TestResolvingIO {
 
-  protected final Encoding eEnc;
-  protected final int iSkipL;
-  protected final String sJsWrtSchm;
-  protected final String sWrtCls;
-  protected final String sJsRdrSchm;
-  protected final String sRdrCls;
-
-  public TestResolvingIO(Encoding encoding, int skipLevel, String jsonWriterSchema, String writerCalls,
-      String jsonReaderSchema, String readerCalls) {
-    this.eEnc = encoding;
-    this.iSkipL = skipLevel;
-    this.sJsWrtSchm = jsonWriterSchema;
-    this.sWrtCls = writerCalls;
-    this.sJsRdrSchm = jsonReaderSchema;
-    this.sRdrCls = readerCalls;
-  }
-
-  @Test
-  public void testIdentical() throws IOException {
-    performTest(eEnc, iSkipL, sJsWrtSchm, sWrtCls, sJsWrtSchm, sWrtCls);
+  @ParameterizedTest
+  @MethodSource("data2")
+  public void testIdentical(Encoding encoding, int skip, String jsonWriterSchema, String writerCalls,
+      String jsonReaderSchema, String readerCalls) throws IOException {
+    performTest(encoding, skip, jsonWriterSchema, writerCalls, jsonWriterSchema, writerCalls);
   }
 
   private static final int COUNT = 10;
 
-  @Test
-  public void testCompatible() throws IOException {
-    performTest(eEnc, iSkipL, sJsWrtSchm, sWrtCls, sJsRdrSchm, sRdrCls);
+  @ParameterizedTest
+  @MethodSource("data2")
+  public void testCompatible(Encoding encoding, int skip, String jsonWriterSchema, String writerCalls,
+      String jsonReaderSchema, String readerCalls) throws IOException {
+    performTest(encoding, skip, jsonWriterSchema, writerCalls, jsonReaderSchema, readerCalls);
   }
 
   private void performTest(Encoding encoding, int skipLevel, String jsonWriterSchema, String writerCalls,
@@ -100,9 +86,8 @@ public class TestResolvingIO {
     TestValidatingIO.check(msg, vi, calls, values, skipLevel);
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data2() {
-    return Arrays.asList(TestValidatingIO.convertTo2dArray(encodings, skipLevels, testSchemas()));
+  public static Stream<Arguments> data2() {
+    return TestValidatingIO.convertTo2dStream(encodings, skipLevels, testSchemas());
   }
 
   static Object[][] encodings = new Object[][] { { Encoding.BINARY }, { Encoding.BLOCKING_BINARY }, { Encoding.JSON } };
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java
index abde027e2..0a55d18a7 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java
@@ -17,53 +17,32 @@
  */
 package org.apache.avro.io;
 
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-
 import org.apache.avro.Schema;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 
-@RunWith(Parameterized.class)
-public class TestResolvingIOResolving {
-  protected TestValidatingIO.Encoding eEnc;
-  protected final int iSkipL;
-  protected final String sJsWrtSchm;
-  protected final String sWrtCls;
-  protected final String sJsRdrSchm;
-  protected final String sRdrCls;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-  protected final Object[] oaWrtVals;
-  protected final Object[] oaRdrVals;
+import java.io.IOException;
+import java.util.stream.Stream;
 
-  public TestResolvingIOResolving(TestValidatingIO.Encoding encoding, int skipLevel, String jsonWriterSchema,
-      String writerCalls, Object[] writerValues, String jsonReaderSchema, String readerCalls, Object[] readerValues) {
-    this.eEnc = encoding;
-    this.iSkipL = skipLevel;
-    this.sJsWrtSchm = jsonWriterSchema;
-    this.sWrtCls = writerCalls;
-    this.oaWrtVals = writerValues;
-    this.sJsRdrSchm = jsonReaderSchema;
-    this.sRdrCls = readerCalls;
-    this.oaRdrVals = readerValues;
-  }
+public class TestResolvingIOResolving {
 
-  @Test
-  public void testResolving() throws IOException {
-    Schema writerSchema = new Schema.Parser().parse(sJsWrtSchm);
-    byte[] bytes = TestValidatingIO.make(writerSchema, sWrtCls, oaWrtVals, eEnc);
-    Schema readerSchema = new Schema.Parser().parse(sJsRdrSchm);
-    TestValidatingIO.print(eEnc, iSkipL, writerSchema, readerSchema, oaWrtVals, oaRdrVals);
-    TestResolvingIO.check(writerSchema, readerSchema, bytes, sRdrCls, oaRdrVals, eEnc, iSkipL);
+  @ParameterizedTest
+  @MethodSource("data3")
+  public void testResolving(TestValidatingIO.Encoding encoding, int skipLevel, String jsonWriterSchema,
+      String writerCalls, Object[] writerValues, String jsonReaderSchema, String readerCalls, Object[] readerValues)
+      throws IOException {
+    Schema writerSchema = new Schema.Parser().parse(jsonWriterSchema);
+    byte[] bytes = TestValidatingIO.make(writerSchema, writerCalls, writerValues, encoding);
+    Schema readerSchema = new Schema.Parser().parse(jsonReaderSchema);
+    TestValidatingIO.print(encoding, skipLevel, writerSchema, readerSchema, writerValues, readerValues);
+    TestResolvingIO.check(writerSchema, readerSchema, bytes, readerCalls, readerValues, encoding, skipLevel);
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data3() {
-    Collection<Object[]> ret = Arrays.asList(TestValidatingIO.convertTo2dArray(TestResolvingIO.encodings,
-        TestResolvingIO.skipLevels, dataForResolvingTests()));
-    return ret;
+  public static Stream<Arguments> data3() {
+    return TestValidatingIO.convertTo2dStream(TestResolvingIO.encodings, TestResolvingIO.skipLevels,
+        dataForResolvingTests());
   }
 
   private static Object[][] dataForResolvingTests() {
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestValidatingIO.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestValidatingIO.java
index 3056d5430..063414fbb 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/TestValidatingIO.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestValidatingIO.java
@@ -17,9 +17,15 @@
  */
 package org.apache.avro.io;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import org.apache.avro.Schema;
+import org.apache.avro.util.Utf8;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -27,20 +33,14 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
-import org.apache.avro.Schema;
-import org.apache.avro.util.Utf8;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
-@RunWith(Parameterized.class)
 public class TestValidatingIO {
   enum Encoding {
     BINARY, BLOCKING_BINARY, JSON,
@@ -48,30 +48,19 @@ public class TestValidatingIO {
 
   private static final Logger LOG = LoggerFactory.getLogger(TestValidatingIO.class);
 
-  private Encoding eEnc;
-  private int iSkipL;
-  private String sJsSch;
-  private String sCl;
-
-  public TestValidatingIO(Encoding enc, int skip, String js, String cls) {
-    this.eEnc = enc;
-    this.iSkipL = skip;
-    this.sJsSch = js;
-    this.sCl = cls;
-  }
-
   private static final int COUNT = 1;
 
-  @Test
-  public void testMain() throws IOException {
+  @ParameterizedTest
+  @MethodSource("data")
+  public void testMain(Encoding enc, int skip, String js, String cls) throws IOException {
     for (int i = 0; i < COUNT; i++) {
-      testOnce(new Schema.Parser().parse(sJsSch), sCl, iSkipL, eEnc);
+      testOnce(new Schema.Parser().parse(js), cls, skip, enc);
     }
   }
 
   private void testOnce(Schema schema, String calls, int skipLevel, Encoding encoding) throws IOException {
     Object[] values = randomValues(calls);
-    print(eEnc, iSkipL, schema, schema, values, values);
+    print(encoding, skipLevel, schema, schema, values, values);
     byte[] bytes = make(schema, calls, values, encoding);
     check(schema, bytes, calls, values, skipLevel, encoding);
   }
@@ -204,7 +193,7 @@ public class TestValidatingIO {
         break;
       }
       default:
-        fail();
+        Assertions.fail();
         break;
       }
     }
@@ -254,7 +243,7 @@ public class TestValidatingIO {
       case 's':
         break;
       default:
-        fail();
+        Assertions.fail();
         break;
       }
     }
@@ -324,25 +313,25 @@ public class TestValidatingIO {
           vi.readNull();
           break;
         case 'B':
-          assertEquals(msg, values[p++], vi.readBoolean());
+          Assertions.assertEquals(values[p++], vi.readBoolean(), msg);
           break;
         case 'I':
-          assertEquals(msg, values[p++], vi.readInt());
+          Assertions.assertEquals(values[p++], vi.readInt(), msg);
           break;
         case 'L':
-          assertEquals(msg, values[p++], vi.readLong());
+          Assertions.assertEquals(values[p++], vi.readLong(), msg);
           break;
         case 'F':
           if (!(values[p] instanceof Float))
-            fail();
+            Assertions.fail();
           float f = (Float) values[p++];
-          assertEquals(msg, f, vi.readFloat(), Math.abs(f / 1000));
+          Assertions.assertEquals(f, vi.readFloat(), Math.abs(f / 1000));
           break;
         case 'D':
           if (!(values[p] instanceof Double))
-            fail();
+            Assertions.fail();
           double d = (Double) values[p++];
-          assertEquals(msg, d, vi.readDouble(), Math.abs(d / 1000));
+          Assertions.assertEquals(d, vi.readDouble(), Math.abs(d / 1000), msg);
           break;
         case 'S':
           extractInt(cs);
@@ -351,7 +340,7 @@ public class TestValidatingIO {
             p++;
           } else {
             String s = (String) values[p++];
-            assertEquals(msg, new Utf8(s), vi.readString(null));
+            Assertions.assertEquals(new Utf8(s), vi.readString(null), msg);
           }
           break;
         case 'K':
@@ -361,7 +350,7 @@ public class TestValidatingIO {
             p++;
           } else {
             String s = (String) values[p++];
-            assertEquals(msg, new Utf8(s), vi.readString(null));
+            Assertions.assertEquals(new Utf8(s), vi.readString(null), msg);
           }
           break;
         case 'b':
@@ -374,7 +363,7 @@ public class TestValidatingIO {
             ByteBuffer bb2 = vi.readBytes(null);
             byte[] actBytes = new byte[bb2.remaining()];
             System.arraycopy(bb2.array(), bb2.position(), actBytes, 0, bb2.remaining());
-            assertArrayEquals(msg, bb, actBytes);
+            Assertions.assertArrayEquals(bb, actBytes, msg);
           }
           break;
         case 'f': {
@@ -386,7 +375,7 @@ public class TestValidatingIO {
             byte[] bb = (byte[]) values[p++];
             byte[] actBytes = new byte[len];
             vi.readFixed(actBytes);
-            assertArrayEquals(msg, bb, actBytes);
+            Assertions.assertArrayEquals(bb, actBytes, msg);
           }
         }
           break;
@@ -395,7 +384,7 @@ public class TestValidatingIO {
           if (level == skipLevel) {
             vi.readEnum();
           } else {
-            assertEquals(msg, e, vi.readEnum());
+            Assertions.assertEquals(e, vi.readEnum(), msg);
           }
         }
           break;
@@ -422,16 +411,16 @@ public class TestValidatingIO {
             continue;
           }
         case ']':
-          assertEquals(msg, 0, counts[level]);
+          Assertions.assertEquals(0, counts[level], msg);
           if (!isEmpty[level]) {
-            assertEquals(msg, 0, vi.arrayNext());
+            Assertions.assertEquals(0, vi.arrayNext(), msg);
           }
           level--;
           break;
         case '}':
-          assertEquals(0, counts[level]);
+          Assertions.assertEquals(0, counts[level]);
           if (!isEmpty[level]) {
-            assertEquals(msg, 0, vi.mapNext());
+            Assertions.assertEquals(0, vi.mapNext(), msg);
           }
           level--;
           break;
@@ -450,28 +439,28 @@ public class TestValidatingIO {
           continue;
         case 'U': {
           int idx = extractInt(cs);
-          assertEquals(msg, idx, vi.readIndex());
+          Assertions.assertEquals(idx, vi.readIndex(), msg);
           continue;
         }
         case 'R':
           ((ResolvingDecoder) vi).readFieldOrder();
           continue;
         default:
-          fail(msg);
+          Assertions.fail(msg);
         }
       } catch (RuntimeException e) {
         throw new RuntimeException(msg, e);
       }
     }
-    assertEquals(msg, values.length, p);
+    Assertions.assertEquals(values.length, p, msg);
   }
 
   private static int skip(String msg, InputScanner cs, Decoder vi, boolean isArray) throws IOException {
     final char end = isArray ? ']' : '}';
     if (isArray) {
-      assertEquals(msg, 0, vi.skipArray());
+      Assertions.assertEquals(0, vi.skipArray(), msg);
     } else if (end == '}') {
-      assertEquals(msg, 0, vi.skipMap());
+      Assertions.assertEquals(0, vi.skipMap(), msg);
     }
     int level = 0;
     int p = 0;
@@ -507,9 +496,8 @@ public class TestValidatingIO {
     throw new RuntimeException("Don't know how to skip");
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data() {
-    return Arrays.asList(convertTo2dArray(encodings, skipLevels, testSchemas()));
+  public static Stream<Arguments> data() {
+    return convertTo2dStream(encodings, skipLevels, testSchemas());
   }
 
   private static Object[][] encodings = new Object[][] { { Encoding.BINARY }, { Encoding.BLOCKING_BINARY },
@@ -517,19 +505,11 @@ public class TestValidatingIO {
 
   private static Object[][] skipLevels = new Object[][] { { -1 }, { 0 }, { 1 }, { 2 }, };
 
-  public static Object[][] convertTo2dArray(final Object[][]... values) {
-    ArrayList<Object[]> ret = new ArrayList<>();
-
+  public static Stream<Arguments> convertTo2dStream(final Object[][]... values) {
     Iterator<Object[]> iter = cartesian(values);
-    while (iter.hasNext()) {
-      Object[] objects = iter.next();
-      ret.add(objects);
-    }
-    Object[][] retArrays = new Object[ret.size()][];
-    for (int i = 0; i < ret.size(); i++) {
-      retArrays[i] = ret.get(i);
-    }
-    return retArrays;
+    Stream<Object[]> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED),
+        false);
+    return stream.map(Arguments::of);
   }
 
   /**
diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/parsing/TestResolvingGrammarGenerator.java b/lang/java/avro/src/test/java/org/apache/avro/io/parsing/TestResolvingGrammarGenerator.java
index 212bc3ad3..c6d885673 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/io/parsing/TestResolvingGrammarGenerator.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/io/parsing/TestResolvingGrammarGenerator.java
@@ -21,8 +21,10 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.StringReader;
+import java.io.UncheckedIOException;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.stream.Stream;
 
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.databind.JsonNode;
@@ -38,29 +40,21 @@ import org.apache.avro.generic.GenericDatumWriter;
 import org.apache.avro.generic.GenericRecordBuilder;
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.EncoderFactory;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import static org.apache.avro.TestSchemas.ENUM1_AB_SCHEMA_NAMESPACE_1;
 import static org.apache.avro.TestSchemas.ENUM1_AB_SCHEMA_NAMESPACE_2;
 
-@RunWith(Parameterized.class)
 public class TestResolvingGrammarGenerator {
-  private final Schema schema;
-  private final JsonNode data;
-
-  public TestResolvingGrammarGenerator(String jsonSchema, String jsonData) throws IOException {
-    this.schema = new Schema.Parser().parse(jsonSchema);
-    JsonFactory factory = new JsonFactory();
-    ObjectMapper mapper = new ObjectMapper(factory);
-
-    this.data = mapper.readTree(new StringReader(jsonData));
-  }
 
-  @Test
-  public void test() throws IOException {
+  @ParameterizedTest
+  @MethodSource("data")
+  void test(Schema schema, JsonNode data) throws IOException {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     EncoderFactory factory = EncoderFactory.get();
     Encoder e = factory.validatingEncoder(schema, factory.binaryEncoder(baos, null));
@@ -70,7 +64,7 @@ public class TestResolvingGrammarGenerator {
   }
 
   @Test
-  public void testRecordMissingRequiredFieldError() throws Exception {
+  void recordMissingRequiredFieldError() throws Exception {
     Schema schemaWithoutField = SchemaBuilder.record("MyRecord").namespace("ns").fields().name("field1").type()
         .stringType().noDefault().endRecord();
     Schema schemaWithField = SchemaBuilder.record("MyRecord").namespace("ns").fields().name("field1").type()
@@ -79,15 +73,15 @@ public class TestResolvingGrammarGenerator {
     byte[] data = writeRecord(schemaWithoutField, record);
     try {
       readRecord(schemaWithField, data);
-      Assert.fail("Expected exception not thrown");
+      Assertions.fail("Expected exception not thrown");
     } catch (AvroTypeException typeException) {
-      Assert.assertEquals("Incorrect exception message",
-          "Found ns.MyRecord, expecting ns.MyRecord, missing required field field2", typeException.getMessage());
+      Assertions.assertEquals("Found ns.MyRecord, expecting ns.MyRecord, missing required field field2",
+          typeException.getMessage(), "Incorrect exception message");
     }
   }
 
   @Test
-  public void testDifferingEnumNamespaces() throws Exception {
+  void differingEnumNamespaces() throws Exception {
     Schema schema1 = SchemaBuilder.record("MyRecord").fields().name("field").type(ENUM1_AB_SCHEMA_NAMESPACE_1)
         .noDefault().endRecord();
     Schema schema2 = SchemaBuilder.record("MyRecord").fields().name("field").type(ENUM1_AB_SCHEMA_NAMESPACE_2)
@@ -95,13 +89,12 @@ public class TestResolvingGrammarGenerator {
     GenericData.EnumSymbol genericEnumSymbol = new GenericData.EnumSymbol(ENUM1_AB_SCHEMA_NAMESPACE_1, "A");
     GenericData.Record record = new GenericRecordBuilder(schema1).set("field", genericEnumSymbol).build();
     byte[] data = writeRecord(schema1, record);
-    Assert.assertEquals(genericEnumSymbol, readRecord(schema1, data).get("field"));
-    Assert.assertEquals(genericEnumSymbol, readRecord(schema2, data).get("field"));
+    Assertions.assertEquals(genericEnumSymbol, readRecord(schema1, data).get("field"));
+    Assertions.assertEquals(genericEnumSymbol, readRecord(schema2, data).get("field"));
   }
 
-  @Parameterized.Parameters
-  public static Collection<Object[]> data() {
-    Collection<Object[]> ret = Arrays.asList(new Object[][] {
+  public static Stream<Arguments> data() {
+    Collection<String[]> ret = Arrays.asList(new String[][] {
         { "{ \"type\": \"record\", \"name\": \"r\", \"fields\": [ " + " { \"name\" : \"f1\", \"type\": \"int\" }, "
             + " { \"name\" : \"f2\", \"type\": \"float\" } " + "] }", "{ \"f2\": 10.4, \"f1\": 10 } " },
         { "{ \"type\": \"enum\", \"name\": \"e\", \"symbols\": " + "[ \"s1\", \"s2\"] }", " \"s1\" " },
@@ -112,7 +105,19 @@ public class TestResolvingGrammarGenerator {
         { "[ \"int\", \"long\" ]", "10" }, { "\"string\"", "\"hello\"" }, { "\"bytes\"", "\"hello\"" },
         { "\"int\"", "10" }, { "\"long\"", "10" }, { "\"float\"", "10.0" }, { "\"double\"", "10.0" },
         { "\"boolean\"", "true" }, { "\"boolean\"", "false" }, { "\"null\"", "null" }, });
-    return ret;
+
+    final JsonFactory factory = new JsonFactory();
+    final ObjectMapper mapper = new ObjectMapper(factory);
+
+    return ret.stream().map((String[] args) -> {
+      Schema schema = new Schema.Parser().parse(args[0]);
+      try {
+        JsonNode data = mapper.readTree(new StringReader(args[1]));
+        return Arguments.of(schema, data);
+      } catch (IOException ex) {
+        throw new UncheckedIOException(ex);
+      }
+    });
   }
 
   private byte[] writeRecord(Schema schema, GenericData.Record record) throws Exception {
diff --git a/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificRecordWithUnion.java b/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificRecordWithUnion.java
index c3b330b28..e64b3f4c2 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificRecordWithUnion.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/specific/TestSpecificRecordWithUnion.java
@@ -29,7 +29,8 @@ import org.apache.avro.io.DatumReader;
 import org.apache.avro.io.DatumWriter;
 import org.apache.avro.io.BinaryEncoder;
 import org.apache.avro.io.Decoder;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -40,7 +41,7 @@ import static org.junit.Assert.assertEquals;
 
 public class TestSpecificRecordWithUnion {
   @Test
-  public void testUnionLogicalDecimalConversion() throws IOException {
+  void unionLogicalDecimalConversion() throws IOException {
     final TestUnionRecord record = TestUnionRecord.newBuilder().setAmount(BigDecimal.ZERO).build();
     final Schema schema = SchemaBuilder.unionOf().nullType().and().type(record.getSchema()).endUnion();
 
diff --git a/lang/java/tools/src/test/java/org/apache/avro/tool/TestRpcProtocolTool.java b/lang/java/tools/src/test/java/org/apache/avro/tool/TestRpcProtocolTool.java
index fddd850df..fcdd2d059 100644
--- a/lang/java/tools/src/test/java/org/apache/avro/tool/TestRpcProtocolTool.java
+++ b/lang/java/tools/src/test/java/org/apache/avro/tool/TestRpcProtocolTool.java
@@ -18,63 +18,37 @@
 package org.apache.avro.tool;
 
 import org.apache.avro.Protocol;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.PrintStream;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
 
 /**
  *
  */
-@RunWith(Parameterized.class)
 public class TestRpcProtocolTool {
 
-  @Parameterized.Parameters(/* name = "{0}" */)
-  public static List<Object[]> data() {
-    return Arrays.asList(new Object[] { "http" }, new Object[] { "avro" });
-  }
-
-  private RpcReceiveTool receive;
-  private Protocol simpleProtocol;
-
-  private String uriScheme;
-
-  public TestRpcProtocolTool(String uriScheme) {
-    this.uriScheme = uriScheme;
-  }
+  @ParameterizedTest
+  @ValueSource(strings = { "http", "avro" })
+  void rpcProtocol(String uriScheme) throws Exception {
 
-  @Before
-  public void setUp() throws Exception {
     String protocolFile = System.getProperty("share.dir", "../../../share") + "/test/schemas/simple.avpr";
 
-    simpleProtocol = Protocol.parse(new File(protocolFile));
+    Protocol simpleProtocol = Protocol.parse(new File(protocolFile));
 
     // start a simple server
     ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
     PrintStream p1 = new PrintStream(baos1);
-    receive = new RpcReceiveTool();
+    RpcReceiveTool receive = new RpcReceiveTool();
+
     receive.run1(null, p1, System.err,
         Arrays.asList(uriScheme + "://0.0.0.0:0/", protocolFile, "hello", "-data", "\"Hello!\""));
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    if (receive != null)
-      receive.server.close(); // force the server to finish
-  }
-
-  @Test
-  public void testRpcProtocol() throws Exception {
 
     // run the actual test
     ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
@@ -86,8 +60,9 @@ public class TestRpcProtocolTool {
 
     p2.flush();
 
-    assertEquals("Expected the simple.avpr protocol to be echoed to standout", simpleProtocol,
-        Protocol.parse(baos2.toString("UTF-8")));
+    Assertions.assertEquals(simpleProtocol, Protocol.parse(baos2.toString("UTF-8")),
+        "Expected the simple.avpr protocol to be echoed to standout");
 
+    receive.server.close(); // force the server to finish
   }
 }
diff --git a/lang/java/trevni/core/src/test/java/org/apache/trevni/TestAllCodecs.java b/lang/java/trevni/core/src/test/java/org/apache/trevni/TestAllCodecs.java
index c58804642..e5bda582f 100644
--- a/lang/java/trevni/core/src/test/java/org/apache/trevni/TestAllCodecs.java
+++ b/lang/java/trevni/core/src/test/java/org/apache/trevni/TestAllCodecs.java
@@ -18,28 +18,17 @@
 
 package org.apache.trevni;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.io.IOException;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Collection;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@RunWith(Parameterized.class)
 public class TestAllCodecs {
-  @Parameterized.Parameters(name = "{index}: codec={0}")
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] { { "bzip2" }, { "null" }, { "snappy" }, { "deflate" }, });
-  }
-
-  @Parameterized.Parameter(0)
-  public String codec;
 
   public static Codec getCodec(String name) {
     MetaData m = new MetaData();
@@ -47,8 +36,9 @@ public class TestAllCodecs {
     return Codec.get(m);
   }
 
-  @Test
-  public void testCodec() throws IOException {
+  @ParameterizedTest
+  @ValueSource(strings = { "bzip2", "null", "snappy", "deflate" })
+  public void testCodec(String codec) throws IOException {
     int inputSize = 500_000;
 
     byte[] input = generateTestData(inputSize);
@@ -76,8 +66,9 @@ public class TestAllCodecs {
     assertEquals(decompressedBuffer, inputByteBuffer);
   }
 
-  @Test
-  public void testCodecSlice() throws IOException {
+  @ParameterizedTest
+  @ValueSource(strings = { "bzip2", "null", "snappy", "deflate" })
+  public void testCodecSlice(String codec) throws IOException {
     int inputSize = 500_000;
     byte[] input = generateTestData(inputSize);
 
diff --git a/lang/java/trevni/core/src/test/java/org/apache/trevni/TestColumnFile.java b/lang/java/trevni/core/src/test/java/org/apache/trevni/TestColumnFile.java
index 6fc36bf67..781476abf 100644
--- a/lang/java/trevni/core/src/test/java/org/apache/trevni/TestColumnFile.java
+++ b/lang/java/trevni/core/src/test/java/org/apache/trevni/TestColumnFile.java
@@ -19,72 +19,66 @@ package org.apache.trevni;
 
 import java.io.File;
 import java.util.Random;
-import java.util.Collection;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.stream.Stream;
 
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.runners.Parameterized.Parameters;
 
-@RunWith(value = Parameterized.class)
 public class TestColumnFile {
 
   private static final File FILE = new File("target", "test.trv");
   private static final int COUNT = 1024 * 64;
 
-  private String codec;
-  private String checksum;
-
-  public TestColumnFile(String codec, String checksum) {
-    this.codec = codec;
-    this.checksum = checksum;
-  }
-
   @Parameters
-  public static Collection<Object[]> codecs() {
-    Object[][] data = new Object[][] { { "null", "null" }, { "snappy", "crc32" }, { "deflate", "crc32" } };
-    return Arrays.asList(data);
+  public static Stream<Arguments> codecs() {
+    return Stream.of(Arguments.of(createFileMeta("null", "null")), Arguments.of(createFileMeta("snappy", "crc32")),
+        Arguments.of(createFileMeta("deflate", "crc32")));
   }
 
-  private ColumnFileMetaData createFileMeta() {
+  private static ColumnFileMetaData createFileMeta(String codec, String checksum) {
     return new ColumnFileMetaData().setCodec(codec).setChecksum(checksum);
   }
 
-  @Test
-  public void testEmptyFile() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void emptyFile(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta());
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta);
     out.writeTo(FILE);
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(0, in.getRowCount());
-    Assert.assertEquals(0, in.getColumnCount());
+    Assertions.assertEquals(0, in.getRowCount());
+    Assertions.assertEquals(0, in.getColumnCount());
     in.close();
   }
 
-  @Test
-  public void testEmptyColumn() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void emptyColumn(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("test", ValueType.INT));
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("test", ValueType.INT));
     out.writeTo(FILE);
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(0, in.getRowCount());
-    Assert.assertEquals(1, in.getColumnCount());
+    Assertions.assertEquals(0, in.getRowCount());
+    Assertions.assertEquals(1, in.getColumnCount());
     ColumnValues<Integer> values = in.getValues("test");
     for (int i : values)
       throw new Exception("no value should be found");
     in.close();
   }
 
-  @Test
-  public void testInts() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void ints(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
 
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("test", ValueType.INT));
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("test", ValueType.INT));
     Random random = TestUtil.createRandom();
     for (int i = 0; i < COUNT; i++)
       out.writeRow(TestUtil.randomLength(random));
@@ -92,22 +86,23 @@ public class TestColumnFile {
 
     random = TestUtil.createRandom();
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(COUNT, in.getRowCount());
-    Assert.assertEquals(1, in.getColumnCount());
+    Assertions.assertEquals(COUNT, in.getRowCount());
+    Assertions.assertEquals(1, in.getColumnCount());
     Iterator<Integer> i = in.getValues("test");
     int count = 0;
     while (i.hasNext()) {
-      Assert.assertEquals(TestUtil.randomLength(random), (int) i.next());
+      Assertions.assertEquals(TestUtil.randomLength(random), (int) i.next());
       count++;
     }
-    Assert.assertEquals(COUNT, count);
+    Assertions.assertEquals(COUNT, count);
   }
 
-  @Test
-  public void testLongs() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void longs(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
 
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("test", ValueType.LONG));
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("test", ValueType.LONG));
     Random random = TestUtil.createRandom();
     for (int i = 0; i < COUNT; i++)
       out.writeRow(random.nextLong());
@@ -115,22 +110,23 @@ public class TestColumnFile {
 
     random = TestUtil.createRandom();
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(COUNT, in.getRowCount());
-    Assert.assertEquals(1, in.getColumnCount());
+    Assertions.assertEquals(COUNT, in.getRowCount());
+    Assertions.assertEquals(1, in.getColumnCount());
     Iterator<Long> i = in.getValues("test");
     int count = 0;
     while (i.hasNext()) {
-      Assert.assertEquals(random.nextLong(), (long) i.next());
+      Assertions.assertEquals(random.nextLong(), (long) i.next());
       count++;
     }
-    Assert.assertEquals(COUNT, count);
+    Assertions.assertEquals(COUNT, count);
   }
 
-  @Test
-  public void testStrings() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void strings(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
 
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("test", ValueType.STRING));
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("test", ValueType.STRING));
     Random random = TestUtil.createRandom();
     for (int i = 0; i < COUNT; i++)
       out.writeRow(TestUtil.randomString(random));
@@ -138,21 +134,22 @@ public class TestColumnFile {
 
     random = TestUtil.createRandom();
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(COUNT, in.getRowCount());
-    Assert.assertEquals(1, in.getColumnCount());
+    Assertions.assertEquals(COUNT, in.getRowCount());
+    Assertions.assertEquals(1, in.getColumnCount());
     Iterator<String> i = in.getValues("test");
     int count = 0;
     while (i.hasNext()) {
-      Assert.assertEquals(TestUtil.randomString(random), i.next());
+      Assertions.assertEquals(TestUtil.randomString(random), i.next());
       count++;
     }
-    Assert.assertEquals(COUNT, count);
+    Assertions.assertEquals(COUNT, count);
   }
 
-  @Test
-  public void testTwoColumn() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void twoColumn(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("a", ValueType.FIXED32),
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("a", ValueType.FIXED32),
         new ColumnMetaData("b", ValueType.STRING));
     Random random = TestUtil.createRandom();
     for (int i = 0; i < COUNT; i++)
@@ -161,24 +158,25 @@ public class TestColumnFile {
 
     random = TestUtil.createRandom();
     ColumnFileReader in = new ColumnFileReader(FILE);
-    Assert.assertEquals(COUNT, in.getRowCount());
-    Assert.assertEquals(2, in.getColumnCount());
+    Assertions.assertEquals(COUNT, in.getRowCount());
+    Assertions.assertEquals(2, in.getColumnCount());
     Iterator<String> i = in.getValues("a");
     Iterator<String> j = in.getValues("b");
     int count = 0;
     while (i.hasNext() && j.hasNext()) {
-      Assert.assertEquals(random.nextInt(), i.next());
-      Assert.assertEquals(TestUtil.randomString(random), j.next());
+      Assertions.assertEquals(random.nextInt(), i.next());
+      Assertions.assertEquals(TestUtil.randomString(random), j.next());
       count++;
     }
-    Assert.assertEquals(COUNT, count);
+    Assertions.assertEquals(COUNT, count);
   }
 
-  @Test
-  public void testSeekLongs() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void seekLongs(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
 
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(), new ColumnMetaData("test", ValueType.LONG));
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta, new ColumnMetaData("test", ValueType.LONG));
     Random random = TestUtil.createRandom();
 
     int seekCount = COUNT / 1024;
@@ -206,16 +204,17 @@ public class TestColumnFile {
 
     for (int i = 0; i < seekCount; i++) {
       v.seek(seekRows[i]);
-      Assert.assertEquals(seekValues[i], v.next());
+      Assertions.assertEquals(seekValues[i], v.next());
     }
 
   }
 
-  @Test
-  public void testSeekStrings() throws Exception {
+  @ParameterizedTest
+  @MethodSource("codecs")
+  void seekStrings(ColumnFileMetaData fileMeta) throws Exception {
     FILE.delete();
 
-    ColumnFileWriter out = new ColumnFileWriter(createFileMeta(),
+    ColumnFileWriter out = new ColumnFileWriter(fileMeta,
         new ColumnMetaData("test", ValueType.STRING).hasIndexValues(true));
 
     Random random = TestUtil.createRandom();
@@ -246,7 +245,7 @@ public class TestColumnFile {
 
     for (int i = 0; i < seekCount; i++) {
       v.seek(seekValues[i]);
-      Assert.assertEquals(seekValues[i], v.next());
+      Assertions.assertEquals(seekValues[i], v.next());
     }
 
   }