Skip to content

feat: Migrate all Java unit tests from JUnit 4 to JUnit Jupiter#2724

Draft
He-Pin wants to merge 1 commit intomainfrom
removeJunit4
Draft

feat: Migrate all Java unit tests from JUnit 4 to JUnit Jupiter#2724
He-Pin wants to merge 1 commit intomainfrom
removeJunit4

Conversation

@He-Pin
Copy link
Member

@He-Pin He-Pin commented Mar 12, 2026

Motivation

Migrate all Java unit tests from JUnit 4 patterns (@ClassRule, @Rule, @RunWith, ExternalResource, extends JUnitSuite) to JUnit 5 Jupiter patterns (@RegisterExtension, @ExtendWith). This improves project maintainability and aligns with the modern testing ecosystem.

Additionally, rename all JUnit5* naming to JUnitJupiter* in test files, since "JUnit Jupiter" is the API name — not tied to version 5. With jupiter-engine already at version 6.0.3, using JUnit5 in class names would be misleading.

This addresses reviewer feedback from @pjfanning:

"Why is this called Junit5 in this new code? v6 is out. Can't we call the new classes JUnitJupiter or something like that?"

Modification

New Files

  • PekkoJUnitJupiterActorSystemResource.java — JUnit Jupiter extension replacing JUnit 4 Rule-based PekkoJUnitActorSystemResource. Implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver. Thread-safe via synchronized methods with a classLevel flag distinguishing static (class-level) from instance (per-test) lifecycle.
  • StreamTestJupiter.java — Base class for stream tests, replacing StreamTest (JUnit 4 version). Delegates to PekkoJUnitJupiterActorSystemResource.
  • ActorTestKitJUnitJupiterTest.java — Renamed from ActorTestKitJUnit5Test.

Migration Patterns Applied (206 files)

Old (JUnit 4) New (JUnit Jupiter)
@ClassRule public static PekkoJUnitActorSystemResource @RegisterExtension static PekkoJUnitJupiterActorSystemResource
@Rule public PekkoJUnitActorSystemResource @RegisterExtension PekkoJUnitJupiterActorSystemResource
extends JUnitSuite (removed — not needed with Jupiter)
@RunWith(JUnitRunner.class) (removed)
@Test(expected = X.class) assertThrows(X.class, () -> {...})
Assert.assertEquals(msg, expected, actual) assertEquals(expected, actual, msg)
Assert.assertTrue(msg, condition) assertTrue(condition, msg)
extends StreamTest extends StreamTestJupiter
@ExtendWith(TestKitJUnit5Extension.class) @ExtendWith(TestKitJUnitJupiterExtension.class)
@JUnit5TestKit @JUnitJupiterTestKit
JUnit5TestKitBuilder JUnitJupiterTestKitBuilder

Backward Compatibility

  • Old JUnit5TestKitBuilder, TestKitJUnit5Extension, JUnit5TestKit annotation in src/main are preserved (not deleted or deprecated — deprecation is a separate concern per @pjfanning).
  • Old PekkoJUnitActorSystemResource and StreamTest preserved for users who still use JUnit 4.
  • JUnit5TestKitBuilderSpec.scala preserved as it tests the old builder.

Dependencies

  • junit-jupiter-engine: 6.0.3
  • junit-platform-launcher: 6.0.3
  • sbt-jupiter-interface: 0.17.0
  • junit-interface: 0.11 (for JUnit 4 vintage compatibility)

Result

  • ✅ All 206 test files migrated
  • ✅ Zero remaining JUnit 4 annotations/imports in test files
  • ✅ Zero printStackTrace calls
  • ✅ Binary compatibility maintained
  • ✅ Local compilation passes (all 11+ modules)
  • ✅ Local tests pass (actor-testkit-typed: 171, actor-tests: 63, stream-tests: 215, docs: 46, coordination: 1, persistence-typed: 3)
  • ✅ Cross-reviewed by 16 AI agents across 5 models (GPT 5.4, Gemini 3 Pro, Claude Opus 4.6, GPT 5.1, PR Reviewer)

References


This code is Apache licensed under the Apache License, Version 2.0.

@He-Pin He-Pin marked this pull request as draft March 12, 2026 05:01
@He-Pin
Copy link
Member Author

He-Pin commented Mar 12, 2026

The javafmt can't run on Java 25:( , in JDK 25 — com.sun.tools.javac.util.Log$DeferredDiagnosticHandler.getDiagnostics() is gone

@He-Pin He-Pin force-pushed the removeJunit4 branch 2 times, most recently from 558a695 to 50a3952 Compare March 12, 2026 10:21
@He-Pin
Copy link
Member Author

He-Pin commented Mar 12, 2026

We should mark JUnit 4 support as deprecated, and mark it since 2.0.0.

@He-Pin He-Pin marked this pull request as ready for review March 12, 2026 11:31
@He-Pin He-Pin requested a review from pjfanning March 12, 2026 14:08
@pjfanning pjfanning added this to the 2.0.0-M2 milestone Mar 12, 2026
@pjfanning
Copy link
Member

pjfanning commented Mar 15, 2026

Why is this called Junit5 in this new code? v6 is out.
Can't we call the new classes JUnitJupiter or something like that?
Junit5 seems like a bad name now.

We already have https://github.com/apache/pekko/blob/main/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/JUnitJupiterTestKitBuilder.scala

I'm thinking about the new classes in this PR

  • StreamTest5.java‎ could be renamed StreamTestJupiter.java
  • PekkoJUnit5ActorSystemResource.java‎ could be renamed PekkoJUnitJupiterActorSystemResource.java
  • Everywhere in your new code where you use TestKitJUnit5Extension, you could use TestKitJUnitJupiterExtension instead (the latter class already exists)

@He-Pin
Copy link
Member Author

He-Pin commented Mar 16, 2026

I will rebase on your current style:)

@He-Pin He-Pin marked this pull request as draft March 16, 2026 03:09
He-Pin added a commit that referenced this pull request Mar 16, 2026
Motivation:
JUnit 4 has reached end-of-life and JUnit 5 (Jupiter) provides significant
improvements. The project already uses jupiter-engine 6.0.3 and has existing
JUnitJupiter-named infrastructure. This migration aligns all test code with
the modern Jupiter naming convention.

Modification:
- Replace @ClassRule/@rule with @RegisterExtension using
  PekkoJUnitJupiterActorSystemResource (renamed from JUnit5 variant)
- Replace StreamTest5 base class with StreamTestJupiter
- Replace TestKitJUnit5Extension with TestKitJUnitJupiterExtension
- Replace @JUnit5TestKit with @JUnitJupiterTestKit annotation
- Replace JUnit5TestKitBuilder with JUnitJupiterTestKitBuilder
- Remove extends JUnitSuite (JUnit 4 base class)
- Migrate Assert to Assertions, @test(expected=...) to assertThrows()
- Add synchronized lifecycle methods for thread safety
- Remove printStackTrace from error handling
- 105 files changed across all test modules

Result:
All Java unit tests now use JUnit Jupiter APIs with consistent JUnitJupiter
naming convention. JUnit 4 support APIs remain available for downstream users.
All tests pass locally.

References:
- PR review feedback: #2724 (comment)
- JUnit 5 User Guide: https://junit.org/junit5/docs/current/user-guide/
@He-Pin He-Pin changed the title chore: Migrate all Java unit tests from JUnit 4 to JUnit 5 feat: Migrate all Java unit tests from JUnit 4 to JUnit Jupiter Mar 16, 2026
He-Pin added a commit that referenced this pull request Mar 16, 2026
Motivation:
JUnit 4 has reached end-of-life and JUnit 5 (Jupiter) provides significant
improvements. The project already uses jupiter-engine 6.0.3 and has existing
JUnitJupiter-named infrastructure. This migration aligns all test code with
the modern Jupiter naming convention.

Modification:
- Replace @ClassRule/@rule with @RegisterExtension using
  PekkoJUnitJupiterActorSystemResource (renamed from JUnit5 variant)
- Replace StreamTest5 base class with StreamTestJupiter
- Replace TestKitJUnit5Extension with TestKitJUnitJupiterExtension
- Replace @JUnit5TestKit with @JUnitJupiterTestKit annotation
- Replace JUnit5TestKitBuilder with JUnitJupiterTestKitBuilder
- Remove extends JUnitSuite (JUnit 4 base class)
- Migrate Assert to Assertions, @test(expected=...) to assertThrows()
- Add synchronized lifecycle methods for thread safety
- Remove printStackTrace from error handling
- 105 files changed across all test modules

Result:
All Java unit tests now use JUnit Jupiter APIs with consistent JUnitJupiter
naming convention. JUnit 4 support APIs remain available for downstream users.
All tests pass locally.

References:
- PR review feedback: #2724 (comment)
- JUnit 5 User Guide: https://junit.org/junit5/docs/current/user-guide/
Motivation:
JUnit 4 has reached end-of-life and JUnit 5 (Jupiter) provides significant
improvements. The project already uses jupiter-engine 6.0.3 and has existing
JUnitJupiter-named infrastructure. This migration aligns all test code with
the modern Jupiter naming convention.

Modification:
- Replace @ClassRule/@rule with @RegisterExtension using
  PekkoJUnitJupiterActorSystemResource (renamed from JUnit5 variant)
- Replace StreamTest5 base class with StreamTestJupiter
- Replace TestKitJUnit5Extension with TestKitJUnitJupiterExtension
- Replace @JUnit5TestKit with @JUnitJupiterTestKit annotation
- Replace JUnit5TestKitBuilder with JUnitJupiterTestKitBuilder
- Remove extends JUnitSuite (JUnit 4 base class)
- Migrate Assert to Assertions, @test(expected=...) to assertThrows()
- Add synchronized lifecycle methods for thread safety
- Remove printStackTrace from error handling
- 105 files changed across all test modules

Result:
All Java unit tests now use JUnit Jupiter APIs with consistent JUnitJupiter
naming convention. JUnit 4 support APIs remain available for downstream users.
All tests pass locally.

References:
- PR review feedback: #2724 (comment)
- JUnit 5 User Guide: https://junit.org/junit5/docs/current/user-guide/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants