10
10
11
11
package org .junit .jupiter .engine .descriptor ;
12
12
13
+ import static java .util .Objects .requireNonNull ;
13
14
import static java .util .stream .Collectors .joining ;
14
15
import static org .apiguardian .api .API .Status .INTERNAL ;
15
16
import static org .junit .jupiter .engine .descriptor .CallbackSupport .invokeAfterCallbacks ;
37
38
import java .util .function .Supplier ;
38
39
39
40
import org .apiguardian .api .API ;
41
+ import org .jspecify .annotations .Nullable ;
40
42
import org .junit .jupiter .api .TestInstance .Lifecycle ;
41
43
import org .junit .jupiter .api .extension .AfterAllCallback ;
42
44
import org .junit .jupiter .api .extension .BeforeAllCallback ;
@@ -92,7 +94,10 @@ public abstract class ClassBasedTestDescriptor extends JupiterTestDescriptor
92
94
93
95
protected final ClassInfo classInfo ;
94
96
97
+ @ Nullable
95
98
private LifecycleMethods lifecycleMethods ;
99
+
100
+ @ Nullable
96
101
private TestInstanceFactory testInstanceFactory ;
97
102
98
103
ClassBasedTestDescriptor (UniqueId uniqueId , Class <?> testClass , Supplier <String > displayNameSupplier ,
@@ -148,7 +153,7 @@ private void validateDisplayNameAnnotation(DiscoveryIssueReporter reporter) {
148
153
}
149
154
150
155
protected void validateCoreLifecycleMethods (DiscoveryIssueReporter reporter ) {
151
- Validatable .reportAndClear (this . lifecycleMethods .discoveryIssues , reporter );
156
+ Validatable .reportAndClear (requireLifecycleMethods () .discoveryIssues , reporter );
152
157
}
153
158
154
159
protected void validateClassTemplateInvocationLifecycleMethods (DiscoveryIssueReporter reporter ) {
@@ -198,15 +203,17 @@ public final JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext
198
203
registerExtensionsFromConstructorParameters (registry , getTestClass ());
199
204
}
200
205
201
- this .lifecycleMethods .beforeAll .forEach (method -> registerExtensionsFromExecutableParameters (registry , method ));
206
+ requireLifecycleMethods ().beforeAll .forEach (
207
+ method -> registerExtensionsFromExecutableParameters (registry , method ));
202
208
// Since registerBeforeEachMethodAdapters() and registerAfterEachMethodAdapters() also
203
209
// invoke registerExtensionsFromExecutableParameters(), we invoke those methods before
204
210
// invoking registerExtensionsFromExecutableParameters() for @AfterAll methods,
205
211
// thereby ensuring proper registration order for extensions registered via @ExtendWith
206
212
// on parameters in lifecycle methods.
207
213
registerBeforeEachMethodAdapters (registry );
208
214
registerAfterEachMethodAdapters (registry );
209
- this .lifecycleMethods .afterAll .forEach (method -> registerExtensionsFromExecutableParameters (registry , method ));
215
+ requireLifecycleMethods ().afterAll .forEach (
216
+ method -> registerExtensionsFromExecutableParameters (registry , method ));
210
217
registerExtensionsFromInstanceFields (registry , getTestClass ());
211
218
212
219
ThrowableCollector throwableCollector = createThrowableCollector ();
@@ -288,6 +295,7 @@ public void cleanUp(JupiterEngineExecutionContext context) throws Exception {
288
295
this .testInstanceFactory = null ;
289
296
}
290
297
298
+ @ Nullable
291
299
private TestInstanceFactory resolveTestInstanceFactory (ExtensionRegistry registry ) {
292
300
List <TestInstanceFactory > factories = registry .getExtensions (TestInstanceFactory .class );
293
301
@@ -347,19 +355,19 @@ protected final TestInstances instantiateTestClass(Optional<TestInstances> outer
347
355
invokeTestInstancePreConstructCallbacks (new DefaultTestInstanceFactoryContext (getTestClass (), outerInstance ),
348
356
registry , extensionContext );
349
357
Object instance = this .testInstanceFactory != null //
350
- ? invokeTestInstanceFactory (outerInstance , extensionContext ) //
358
+ ? invokeTestInstanceFactory (this . testInstanceFactory , outerInstance , extensionContext ) //
351
359
: invokeTestClassConstructor (outerInstance , registry , extensionContext );
352
360
return outerInstances .map (instances -> DefaultTestInstances .of (instances , instance )) //
353
361
.orElse (DefaultTestInstances .of (instance ));
354
362
}
355
363
356
- private Object invokeTestInstanceFactory (Optional <Object > outerInstance ,
364
+ private Object invokeTestInstanceFactory (TestInstanceFactory testInstanceFactory , Optional <Object > outerInstance ,
357
365
ExtensionContextSupplier extensionContext ) {
358
366
Object instance ;
359
367
360
368
try {
361
- ExtensionContext actualExtensionContext = extensionContext .get (this . testInstanceFactory );
362
- instance = this . testInstanceFactory .createTestInstance (
369
+ ExtensionContext actualExtensionContext = extensionContext .get (testInstanceFactory );
370
+ instance = testInstanceFactory .createTestInstance (
363
371
new DefaultTestInstanceFactoryContext (getTestClass (), outerInstance ), actualExtensionContext );
364
372
}
365
373
catch (Throwable throwable ) {
@@ -370,7 +378,7 @@ private Object invokeTestInstanceFactory(Optional<Object> outerInstance,
370
378
}
371
379
372
380
String message = "TestInstanceFactory [%s] failed to instantiate test class [%s]" .formatted (
373
- this . testInstanceFactory .getClass ().getName (), getTestClass ().getName ());
381
+ testInstanceFactory .getClass ().getName (), getTestClass ().getName ());
374
382
if (StringUtils .isNotBlank (throwable .getMessage ())) {
375
383
message += ": " + throwable .getMessage ();
376
384
}
@@ -390,7 +398,7 @@ private Object invokeTestInstanceFactory(Optional<Object> outerInstance,
390
398
instanceClassName += "@" + Integer .toHexString (System .identityHashCode (instanceClass ));
391
399
}
392
400
String message = "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s]." .formatted (
393
- this . testInstanceFactory .getClass ().getName (), testClassName , instanceClassName );
401
+ testInstanceFactory .getClass ().getName (), testClassName , instanceClassName );
394
402
395
403
throw new TestInstantiationException (message );
396
404
}
@@ -438,7 +446,7 @@ private void invokeBeforeAllMethods(JupiterEngineExecutionContext context) {
438
446
ThrowableCollector throwableCollector = context .getThrowableCollector ();
439
447
Object testInstance = extensionContext .getTestInstance ().orElse (null );
440
448
441
- for (Method method : this . lifecycleMethods .beforeAll ) {
449
+ for (Method method : requireLifecycleMethods () .beforeAll ) {
442
450
throwableCollector .execute (() -> {
443
451
try {
444
452
executableInvoker .invoke (method , testInstance , extensionContext , registry ,
@@ -467,7 +475,7 @@ private void invokeAfterAllMethods(JupiterEngineExecutionContext context) {
467
475
ThrowableCollector throwableCollector = context .getThrowableCollector ();
468
476
Object testInstance = extensionContext .getTestInstance ().orElse (null );
469
477
470
- this . lifecycleMethods .afterAll .forEach (method -> throwableCollector .execute (() -> {
478
+ requireLifecycleMethods () .afterAll .forEach (method -> throwableCollector .execute (() -> {
471
479
try {
472
480
executableInvoker .invoke (method , testInstance , extensionContext , registry ,
473
481
ReflectiveInterceptorCall .ofVoidMethod (InvocationInterceptor ::interceptAfterAllMethod ));
@@ -500,13 +508,13 @@ private boolean isPerClassLifecycle(JupiterEngineExecutionContext context) {
500
508
}
501
509
502
510
private void registerBeforeEachMethodAdapters (ExtensionRegistrar registrar ) {
503
- registerMethodsAsExtensions (this . lifecycleMethods .beforeEach , registrar ,
511
+ registerMethodsAsExtensions (requireLifecycleMethods () .beforeEach , registrar ,
504
512
this ::synthesizeBeforeEachMethodAdapter );
505
513
}
506
514
507
515
private void registerAfterEachMethodAdapters (ExtensionRegistrar registrar ) {
508
516
// Make a local copy since findAfterEachMethods() returns an immutable list.
509
- List <Method > afterEachMethods = new ArrayList <>(this . lifecycleMethods .afterEach );
517
+ List <Method > afterEachMethods = new ArrayList <>(requireLifecycleMethods () .afterEach );
510
518
511
519
// Since the bottom-up ordering of afterEachMethods will later be reversed when the
512
520
// synthesized AfterEachMethodAdapters are executed within TestMethodTestDescriptor,
@@ -546,14 +554,21 @@ private void invokeMethodInExtensionContext(Method method, ExtensionContext cont
546
554
ReflectiveInterceptorCall .ofVoidMethod (interceptorCall ));
547
555
}
548
556
557
+ private LifecycleMethods requireLifecycleMethods () {
558
+ return requireNonNull (this .lifecycleMethods );
559
+ }
560
+
549
561
protected static class ClassInfo {
550
562
551
563
private final List <DiscoveryIssue > discoveryIssues = new ArrayList <>();
552
564
553
565
final Class <?> testClass ;
554
566
final Set <TestTag > tags ;
555
567
final Lifecycle lifecycle ;
568
+
569
+ @ Nullable
556
570
ExecutionMode defaultChildExecutionMode ;
571
+
557
572
final ExclusiveResourceCollector exclusiveResourceCollector ;
558
573
559
574
ClassInfo (Class <?> testClass , JupiterConfiguration configuration ) {
0 commit comments