or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# JUnit Jupiter Migration Support

1

2

JUnit Jupiter Migration Support provides support for JUnit 4 rules within JUnit Jupiter, enabling legacy test infrastructure to work with JUnit 5. This module facilitates the migration of large JUnit 4 codebases by allowing existing rules to continue working unchanged within JUnit Jupiter test classes.

3

4

## Package Information

5

6

- **Package Name**: junit-jupiter-migrationsupport

7

- **Package Type**: maven

8

- **Language**: Java

9

- **Group ID**: org.junit.jupiter

10

- **Version**: 5.12.2

11

- **Installation**: Add Maven dependency:

12

13

```xml

14

<dependency>

15

<groupId>org.junit.jupiter</groupId>

16

<artifactId>junit-jupiter-migrationsupport</artifactId>

17

<version>5.12.2</version>

18

<scope>test</scope>

19

</dependency>

20

```

21

22

Gradle:

23

24

```gradle

25

testImplementation 'org.junit.jupiter:junit-jupiter-migrationsupport:5.12.2'

26

```

27

28

## Core Imports

29

30

```java

31

// Main annotations for enabling migration support

32

import org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport;

33

import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;

34

35

// Core extension classes (STABLE API)

36

import org.junit.jupiter.migrationsupport.rules.ExternalResourceSupport;

37

import org.junit.jupiter.migrationsupport.rules.VerifierSupport;

38

import org.junit.jupiter.migrationsupport.rules.ExpectedExceptionSupport;

39

import org.junit.jupiter.migrationsupport.conditions.IgnoreCondition;

40

41

// Advanced adapter classes (INTERNAL API - for advanced usage)

42

import org.junit.jupiter.migrationsupport.rules.adapter.GenericBeforeAndAfterAdvice;

43

import org.junit.jupiter.migrationsupport.rules.adapter.AbstractTestRuleAdapter;

44

import org.junit.jupiter.migrationsupport.rules.adapter.ExternalResourceAdapter;

45

import org.junit.jupiter.migrationsupport.rules.adapter.VerifierAdapter;

46

import org.junit.jupiter.migrationsupport.rules.adapter.ExpectedExceptionAdapter;

47

48

// Rule member classes (INTERNAL API - for advanced usage)

49

import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember;

50

import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedField;

51

import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMethod;

52

```

53

54

## Basic Usage

55

56

### Enable Full Migration Support

57

58

```java

59

import org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport;

60

import org.junit.jupiter.api.Test;

61

import org.junit.Rule;

62

import org.junit.rules.TemporaryFolder;

63

64

@EnableJUnit4MigrationSupport

65

public class MyMigratedTest {

66

67

@Rule

68

public TemporaryFolder tempFolder = new TemporaryFolder();

69

70

@Test

71

public void testWithRule() {

72

// Your existing JUnit 4 test code using tempFolder rule

73

// continues to work unchanged

74

}

75

}

76

```

77

78

### Enable Selective Migration Support

79

80

```java

81

import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;

82

import org.junit.jupiter.api.Test;

83

import org.junit.Rule;

84

import org.junit.rules.TemporaryFolder;

85

86

@EnableRuleMigrationSupport

87

public class MySelectiveTest {

88

89

@Rule

90

public TemporaryFolder tempFolder = new TemporaryFolder();

91

92

@Test

93

public void testWithRule() {

94

// JUnit 4 rules work, but @Ignore annotation support not enabled

95

}

96

}

97

```

98

99

## Architecture

100

101

JUnit Jupiter Migration Support is built around several key components:

102

103

- **Migration Annotations**: Class-level annotations that enable rule support for test classes

104

- **Extension Classes**: JUnit Jupiter extensions that handle rule lifecycle integration (STABLE API)

105

- **Adapter System**: Internal adapter pattern that converts JUnit 4 rules into JUnit Jupiter extension callbacks

106

- **Member Detection**: Discovers @Rule-annotated fields and methods in test classes

107

- **Condition Support**: Enables JUnit 4's @Ignore annotation functionality

108

109

The module exports 5 packages:

110

- `org.junit.jupiter.migrationsupport` - Core annotations

111

- `org.junit.jupiter.migrationsupport.conditions` - Condition support

112

- `org.junit.jupiter.migrationsupport.rules` - Rule support extensions

113

- `org.junit.jupiter.migrationsupport.rules.adapter` - Internal adapter classes

114

- `org.junit.jupiter.migrationsupport.rules.member` - Internal member classes

115

116

The module supports both @Rule-annotated fields and methods, maintaining backward compatibility with existing JUnit 4 test infrastructure.

117

118

## Capabilities

119

120

### Full Migration Support

121

122

Enables complete JUnit 4 migration support including all rule types and @Ignore annotation support.

123

124

```java { .api }

125

/**

126

* Class-level annotation that enables all JUnit 4 migration support within JUnit Jupiter.

127

* This composed annotation registers all extensions supported by @EnableRuleMigrationSupport

128

* and provides support for JUnit 4's @Ignore annotation.

129

*

130

* API Status: STABLE (since 5.7)

131

* Since: 5.4

132

*/

133

@Target(ElementType.TYPE)

134

@Retention(RetentionPolicy.RUNTIME)

135

@EnableRuleMigrationSupport

136

@ExtendWith(IgnoreCondition.class)

137

public @interface EnableJUnit4MigrationSupport {

138

}

139

```

140

141

### Rule Migration Support

142

143

Enables native JUnit 4 rule support for Verifier, ExternalResource, and ExpectedException rules.

144

145

```java { .api }

146

/**

147

* Class-level annotation that enables native JUnit 4 rule support within JUnit Jupiter.

148

* Supports rules of type Verifier, ExternalResource, and ExpectedException.

149

*

150

* API Status: STABLE (since 5.7)

151

* Since: 5.0

152

*/

153

@Target(ElementType.TYPE)

154

@Retention(RetentionPolicy.RUNTIME)

155

@ExtendWith(ExternalResourceSupport.class)

156

@ExtendWith(VerifierSupport.class)

157

@ExtendWith(ExpectedExceptionSupport.class)

158

public @interface EnableRuleMigrationSupport {

159

}

160

```

161

162

### External Resource Support

163

164

Provides native support for subclasses of the ExternalResource rule from JUnit 4.

165

166

```java { .api }

167

/**

168

* Extension providing native support for subclasses of ExternalResource rule from JUnit 4.

169

* Supports both @Rule-annotated fields and methods.

170

*

171

* API Status: STABLE (since 5.7)

172

* Since: 5.0

173

*/

174

public class ExternalResourceSupport implements BeforeEachCallback, AfterEachCallback {

175

176

/**

177

* Creates a new ExternalResourceSupport instance.

178

*/

179

public ExternalResourceSupport();

180

181

/**

182

* Called before each test method execution to set up external resources.

183

* @param context the current extension context

184

* @throws Exception if resource setup fails

185

*/

186

@Override

187

public void beforeEach(ExtensionContext context) throws Exception;

188

189

/**

190

* Called after each test method execution to clean up external resources.

191

* @param context the current extension context

192

* @throws Exception if resource cleanup fails

193

*/

194

@Override

195

public void afterEach(ExtensionContext context) throws Exception;

196

}

197

```

198

199

### Verifier Support

200

201

Provides native support for subclasses of the Verifier rule from JUnit 4.

202

203

```java { .api }

204

/**

205

* Extension providing native support for subclasses of Verifier rule from JUnit 4.

206

* Supports both @Rule-annotated fields and methods.

207

*

208

* API Status: STABLE (since 5.7)

209

* Since: 5.0

210

*/

211

public class VerifierSupport implements AfterEachCallback {

212

213

/**

214

* Creates a new VerifierSupport instance.

215

*/

216

public VerifierSupport();

217

218

/**

219

* Called after each test method execution to perform verification.

220

* @param context the current extension context

221

* @throws Exception if verification fails

222

*/

223

@Override

224

public void afterEach(ExtensionContext context) throws Exception;

225

}

226

```

227

228

### Expected Exception Support

229

230

Provides native support for the ExpectedException rule from JUnit 4.

231

232

```java { .api }

233

/**

234

* Extension providing native support for the ExpectedException rule from JUnit 4.

235

* Handles test execution exceptions and validates expected exceptions.

236

*

237

* API Status: STABLE (since 5.7)

238

* Since: 5.0

239

*/

240

public class ExpectedExceptionSupport implements AfterEachCallback, TestExecutionExceptionHandler {

241

242

/**

243

* Creates a new ExpectedExceptionSupport instance.

244

*/

245

public ExpectedExceptionSupport();

246

247

/**

248

* Handles test execution exceptions, checking against expected exceptions.

249

* @param context the current extension context

250

* @param throwable the exception that occurred during test execution

251

* @throws Throwable if the exception should not be handled

252

*/

253

@Override

254

public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable;

255

256

/**

257

* Called after each test method execution to validate expected exceptions.

258

* @param context the current extension context

259

* @throws Exception if expected exception validation fails

260

*/

261

@Override

262

public void afterEach(ExtensionContext context) throws Exception;

263

}

264

```

265

266

### Ignore Condition Support

267

268

ExecutionCondition that supports JUnit 4's @Ignore annotation for disabling test classes and methods.

269

270

```java { .api }

271

/**

272

* ExecutionCondition that supports JUnit 4's @Ignore annotation.

273

* Containers/tests are disabled if @Ignore is present on the test class or method.

274

*

275

* API Status: STABLE (since 5.7)

276

* Since: 5.4

277

*/

278

public class IgnoreCondition implements ExecutionCondition {

279

280

/**

281

* Creates a new IgnoreCondition instance.

282

*/

283

public IgnoreCondition();

284

285

/**

286

* Evaluates the execution condition based on the presence of @Ignore annotation.

287

* @param context the current extension context

288

* @return ConditionEvaluationResult indicating whether execution should proceed

289

*/

290

@Override

291

public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context);

292

}

293

```

294

295

### Advanced Adapter Support

296

297

**Note**: The following adapter classes are part of the INTERNAL API but are exported by the module for advanced usage scenarios.

298

299

#### Generic Before/After Advice Interface

300

301

Base interface for generic before/after advice used by rule adapters.

302

303

```java { .api }

304

/**

305

* Interface for generic before/after advice used by rule adapters.

306

*

307

* API Status: INTERNAL (since 5.0)

308

*/

309

public interface GenericBeforeAndAfterAdvice {

310

311

/**

312

* Called before test execution. Default implementation does nothing.

313

*/

314

default void before();

315

316

/**

317

* Handles test execution exceptions. Default implementation does nothing.

318

* @param cause the exception that occurred during test execution

319

* @throws Throwable if the exception should be rethrown

320

*/

321

default void handleTestExecutionException(Throwable cause) throws Throwable;

322

323

/**

324

* Called after test execution. Default implementation does nothing.

325

*/

326

default void after();

327

}

328

```

329

330

#### Abstract Test Rule Adapter

331

332

Base adapter class for converting JUnit 4 TestRule to JUnit Jupiter extensions.

333

334

```java { .api }

335

/**

336

* Base adapter class for converting JUnit 4 TestRule to JUnit Jupiter extensions.

337

*

338

* API Status: INTERNAL (since 5.0)

339

*/

340

public abstract class AbstractTestRuleAdapter implements GenericBeforeAndAfterAdvice {

341

342

/**

343

* Creates a new adapter for the specified rule-annotated member.

344

* @param annotatedMember the @Rule-annotated field or method

345

* @param adapteeClass the expected rule class type

346

*/

347

public AbstractTestRuleAdapter(TestRuleAnnotatedMember annotatedMember, Class<? extends TestRule> adapteeClass);

348

349

/**

350

* Executes a method on the target rule with no parameters.

351

* @param name the method name to execute

352

* @return the method result

353

*/

354

protected Object executeMethod(String name);

355

356

/**

357

* Executes a method on the target rule with specified parameters.

358

* @param methodName the method name to execute

359

* @param parameterTypes the parameter types

360

* @param arguments the method arguments

361

* @return the method result

362

*/

363

protected Object executeMethod(String methodName, Class<?>[] parameterTypes, Object... arguments);

364

}

365

```

366

367

#### External Resource Adapter

368

369

Adapter for ExternalResource rules.

370

371

```java { .api }

372

/**

373

* Adapter for ExternalResource rules.

374

*

375

* API Status: INTERNAL (since 5.0)

376

*/

377

public class ExternalResourceAdapter extends AbstractTestRuleAdapter {

378

379

/**

380

* Creates a new ExternalResourceAdapter for the specified annotated member.

381

* @param annotatedMember the @Rule-annotated field or method containing an ExternalResource

382

*/

383

public ExternalResourceAdapter(TestRuleAnnotatedMember annotatedMember);

384

385

/**

386

* Called before test execution to set up the external resource.

387

*/

388

@Override

389

public void before();

390

391

/**

392

* Called after test execution to clean up the external resource.

393

*/

394

@Override

395

public void after();

396

}

397

```

398

399

#### Verifier Adapter

400

401

Adapter for Verifier rules.

402

403

```java { .api }

404

/**

405

* Adapter for Verifier rules.

406

*

407

* API Status: INTERNAL (since 5.0)

408

*/

409

public class VerifierAdapter extends AbstractTestRuleAdapter {

410

411

/**

412

* Creates a new VerifierAdapter for the specified annotated member.

413

* @param annotatedMember the @Rule-annotated field or method containing a Verifier

414

*/

415

public VerifierAdapter(TestRuleAnnotatedMember annotatedMember);

416

417

/**

418

* Called after test execution to perform verification.

419

*/

420

@Override

421

public void after();

422

}

423

```

424

425

#### Expected Exception Adapter

426

427

Adapter for ExpectedException rules.

428

429

```java { .api }

430

/**

431

* Adapter for ExpectedException rules.

432

*

433

* API Status: INTERNAL (since 5.0)

434

*/

435

public class ExpectedExceptionAdapter extends AbstractTestRuleAdapter {

436

437

/**

438

* Creates a new ExpectedExceptionAdapter for the specified annotated member.

439

* @param annotatedMember the @Rule-annotated field or method containing an ExpectedException

440

*/

441

public ExpectedExceptionAdapter(TestRuleAnnotatedMember annotatedMember);

442

443

/**

444

* Handles test execution exceptions, checking against expected exceptions.

445

* @param cause the exception that occurred during test execution

446

* @throws Throwable if the exception should not be handled

447

*/

448

@Override

449

public void handleTestExecutionException(Throwable cause) throws Throwable;

450

451

/**

452

* Called after test execution to validate expected exceptions.

453

*/

454

@Override

455

public void after();

456

}

457

```

458

459

### Rule Member Support

460

461

**Note**: The following member classes are part of the INTERNAL API but are exported by the module for advanced usage scenarios.

462

463

#### Test Rule Annotated Member Interface

464

465

Interface representing a @Rule-annotated member (field or method).

466

467

```java { .api }

468

/**

469

* Interface representing a @Rule-annotated member (field or method).

470

* Used internally by the migration support system.

471

*

472

* API Status: INTERNAL (since 5.0)

473

*/

474

public interface TestRuleAnnotatedMember {

475

476

/**

477

* Returns the TestRule instance from this annotated member.

478

* @return the TestRule instance

479

*/

480

TestRule getTestRule();

481

}

482

```

483

484

#### Test Rule Annotated Field

485

486

Represents a @Rule-annotated field containing a TestRule instance.

487

488

```java { .api }

489

/**

490

* Represents a @Rule-annotated field containing a TestRule instance.

491

*

492

* API Status: INTERNAL (since 5.1)

493

*/

494

public class TestRuleAnnotatedField implements TestRuleAnnotatedMember {

495

496

/**

497

* Creates a new TestRuleAnnotatedField for the specified field.

498

* @param testInstance the test instance containing the field

499

* @param field the @Rule-annotated field

500

*/

501

public TestRuleAnnotatedField(Object testInstance, Field field);

502

}

503

```

504

505

#### Test Rule Annotated Method

506

507

Represents a @Rule-annotated method that returns a TestRule instance.

508

509

```java { .api }

510

/**

511

* Represents a @Rule-annotated method that returns a TestRule instance.

512

*

513

* API Status: INTERNAL (since 5.1)

514

*/

515

public class TestRuleAnnotatedMethod implements TestRuleAnnotatedMember {

516

517

/**

518

* Creates a new TestRuleAnnotatedMethod for the specified method.

519

* @param testInstance the test instance containing the method

520

* @param method the @Rule-annotated method

521

*/

522

public TestRuleAnnotatedMethod(Object testInstance, Method method);

523

}

524

```

525

526

## Types

527

528

### JUnit Jupiter Extension Types

529

530

```java { .api }

531

// Core JUnit Jupiter extension interfaces used by migration support

532

// From org.junit.jupiter.api.extension package

533

534

interface BeforeEachCallback extends Extension {

535

/**

536

* Callback that is invoked before each test is invoked.

537

* @param context the current extension context

538

* @throws Exception if callback execution fails

539

*/

540

void beforeEach(ExtensionContext context) throws Exception;

541

}

542

543

interface AfterEachCallback extends Extension {

544

/**

545

* Callback that is invoked after each test has been invoked.

546

* @param context the current extension context

547

* @throws Exception if callback execution fails

548

*/

549

void afterEach(ExtensionContext context) throws Exception;

550

}

551

552

interface TestExecutionExceptionHandler extends Extension {

553

/**

554

* Handle the supplied throwable.

555

* @param context the current extension context

556

* @param throwable the Throwable to handle

557

* @throws Throwable if handling fails or the exception should be rethrown

558

*/

559

void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable;

560

}

561

562

interface ExecutionCondition extends Extension {

563

/**

564

* Evaluate the execution condition for the supplied ExtensionContext.

565

* @param context the current extension context

566

* @return the result of evaluating the condition

567

*/

568

ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context);

569

}

570

571

interface ExtensionContext {

572

/**

573

* Get the AnnotatedElement corresponding to the current extension context.

574

*/

575

Optional<AnnotatedElement> getElement();

576

577

/**

578

* Get the test instance associated with the current test or container.

579

*/

580

Object getRequiredTestInstance();

581

582

/**

583

* Get the Class associated with the current test or container.

584

*/

585

Class<?> getRequiredTestClass();

586

587

/**

588

* Get the unique ID of the current test or container.

589

*/

590

String getUniqueId();

591

592

/**

593

* Get the Store for the supplied Namespace.

594

*/

595

Store getStore(Namespace namespace);

596

}

597

598

interface ConditionEvaluationResult {

599

/**

600

* Whether the container or test should be disabled.

601

*/

602

boolean isDisabled();

603

604

/**

605

* Get the reason why the container or test should be disabled or enabled.

606

*/

607

Optional<String> getReason();

608

609

/**

610

* Factory method for creating enabled results.

611

*/

612

static ConditionEvaluationResult enabled(String reason);

613

614

/**

615

* Factory method for creating disabled results.

616

*/

617

static ConditionEvaluationResult disabled(String reason);

618

}

619

```

620

621

### JUnit 4 Rule Types

622

623

```java { .api }

624

// JUnit 4 types referenced by migration support

625

// From org.junit.rules package

626

627

interface TestRule {

628

/**

629

* Modifies the method-running Statement to implement this test-running rule.

630

* @param base the Statement to be modified

631

* @param description a Description of the test implemented in base

632

* @return a new statement, which may be the same as base

633

*/

634

Statement apply(Statement base, Description description);

635

}

636

637

abstract class Verifier implements TestRule {

638

/**

639

* Override this to add verification logic.

640

* @throws Throwable if verification fails

641

*/

642

protected abstract void verify() throws Throwable;

643

}

644

645

abstract class ExternalResource implements TestRule {

646

/**

647

* Override to set up your specific external resource.

648

* @throws Throwable if setup fails

649

*/

650

protected void before() throws Throwable;

651

652

/**

653

* Override to tear down your specific external resource.

654

*/

655

protected void after();

656

}

657

658

class ExpectedException implements TestRule {

659

/**

660

* Returns a Rule that expects no exception to be thrown.

661

*/

662

public static ExpectedException none();

663

664

/**

665

* Specifies the failure message for tests that are expected to throw an exception but do not.

666

* @param message exception message

667

*/

668

public void reportMissingExceptionWithMessage(String message);

669

670

/**

671

* Specifies that the test is expected to throw an exact type of exception.

672

* @param type the exception type

673

*/

674

public void expect(Class<? extends Throwable> type);

675

676

/**

677

* Specifies that the test is expected to throw an exception with the given message.

678

* @param message the expected message

679

*/

680

public void expectMessage(String message);

681

}

682

```

683

684

### Java Reflection Types

685

686

```java { .api }

687

// Java reflection types used by migration support

688

// From java.lang.reflect package

689

690

class Field extends AccessibleObject implements Member {

691

// Standard Java reflection Field class

692

}

693

694

class Method extends Executable {

695

// Standard Java reflection Method class

696

}

697

698

interface AnnotatedElement {

699

// Standard Java reflection AnnotatedElement interface

700

}

701

```

702

703

## Error Handling

704

705

The migration support extensions handle various error scenarios:

706

707

- **Rule instantiation failures**: If @Rule-annotated methods fail to return valid TestRule instances

708

- **Test execution exceptions**: Properly routes exceptions through rule adapters for expected exception handling

709

- **Resource cleanup failures**: Ensures proper cleanup even when exceptions occur during test execution

710

- **Invalid rule types**: Only supports Verifier, ExternalResource, and ExpectedException rule types

711

712

## Limitations

713

714

- **Limited Rule Support**: Only supports subclasses of `org.junit.rules.Verifier`, `org.junit.rules.ExternalResource`, and `org.junit.rules.ExpectedException`

715

- **No Arbitrary TestRule Support**: General support for arbitrary `org.junit.rules.TestRule` implementations is not possible within the JUnit Jupiter extension model

716

- **Migration Purpose**: Primarily intended for migrating existing JUnit 4 codebases, not for new development

717

- **Import Statements**: Existing JUnit 4 rule import statements remain unchanged, including `org.junit.Rule` annotations

718

719

## Migration Guidelines

720

721

1. **Use for Legacy Code**: This module is designed for migrating existing JUnit 4 test suites with minimal changes

722

2. **Prefer Native Extensions**: For new development, use JUnit Jupiter's native extension model instead of JUnit 4 rules

723

3. **Gradual Migration**: Enable migration support to allow time for converting rules to native extensions

724

4. **Rule Compatibility**: Verify that your existing rules are subclasses of supported rule types

725

5. **Annotation Placement**: Apply migration annotations at the class level to enable rule support for the entire test class