Skip to content

Commit bcc6fa4

Browse files
committed
PreInterruptCallback extension
Added PreInterruptCallback extension to allow to hook into the @timeout extension before the executing Thread is interrupted. The default implementation of PreInterruptCallback will simply print the stacks of all Thread to System.err. It is disabled by default and must be enabled with: junit.jupiter.execution.timeout.threaddump.enabled = true Issue: #2938
1 parent 72d643c commit bcc6fa4

35 files changed

+573
-51
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0-M1.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ JUnit repository on GitHub.
7979
a test-scoped `ExtensionContext` in `Extension` methods called during test class
8080
instantiation. This behavior will become the default in future versions of JUnit.
8181
* `@TempDir` is now supported on test class constructors.
82+
* Added `PreInterruptCallback`
8283

8384

8485
[[release-notes-5.12.0-M1-junit-vintage]]

documentation/src/docs/asciidoc/user-guide/extensions.adoc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,21 @@ test methods.
715715
include::{testDir}/example/exception/MultipleHandlersTestCase.java[tags=user_guide]
716716
----
717717

718+
[[extensions-preinterrupt-callback]]
719+
=== PreInterrupt Callback
720+
721+
`{PreInterruptCallback}` defines the API for `Extensions` that wish to react on
722+
`Thread.interrupt()` calls issued by Jupiter before the `Thread.interrupt()` is executed.
723+
724+
This can be used to dump stacks for diagnostics, when the `Timeout` extension
725+
interrupts tests.
726+
727+
There is also a default implementation available, which will dump the stacks of all
728+
`Threads` to `System.err`.
729+
This default implementation need to be enabled with the
730+
<<running-tests-config-params,configuration parameter>>:
731+
`junit.jupiter.execution.timeout.threaddump.enabled`
732+
718733
[[extensions-intercepting-invocations]]
719734
=== Intercepting Invocations
720735

documentation/src/docs/asciidoc/user-guide/writing-tests.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,6 +2658,12 @@ NOTE: If you need more control over polling intervals and greater flexibility wi
26582658
asynchronous tests, consider using a dedicated library such as
26592659
link:https://github.com/awaitility/awaitility[Awaitility].
26602660

2661+
[[writing-tests-dump-stack-timeout]]
2662+
=== Dump Stacks on Timeout
2663+
2664+
It can be helpful for debugging to dump the stacks of all Threads, when a Timeout happened.
2665+
The <<extensions-preinterrupt-callback, PreInterruptCallback>> provides a default
2666+
implementation for that.
26612667

26622668
[[writing-tests-declarative-timeouts-mode]]
26632669
==== Disable @Timeout Globally

junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
package org.junit.jupiter.api.extension;
1212

13+
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
1314
import static org.apiguardian.api.API.Status.STABLE;
1415

1516
import java.lang.reflect.AnnotatedElement;
@@ -401,6 +402,17 @@ default void publishReportEntry(String value) {
401402
@API(status = STABLE, since = "5.11")
402403
ExecutableInvoker getExecutableInvoker();
403404

405+
/**
406+
* Returns a list of registered extension at this context of the passed {@code extensionType}.
407+
*
408+
* @param <E> the extension type
409+
* @param extensionType the extension type
410+
* @return the list of extensions
411+
* @since 5.12
412+
*/
413+
@API(status = EXPERIMENTAL, since = "5.12")
414+
<E extends Extension> List<E> getExtensions(Class<E> extensionType);
415+
404416
/**
405417
* {@code Store} provides methods for extensions to save and retrieve data.
406418
*/
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2015-2024 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.jupiter.api.extension;
12+
13+
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
14+
15+
import org.apiguardian.api.API;
16+
17+
/**
18+
* {@code PreInterruptCallback} defines the API for {@link Extension
19+
* Extensions} that wish to react on {@link Thread#interrupt()} calls issued by Jupiter
20+
* before the {@link Thread#interrupt()} is executed.
21+
*
22+
* <p>This can be used to e.g. dump stacks for diagnostics, when the {@link org.junit.jupiter.api.Timeout}
23+
* extension is used.</p>
24+
*
25+
* <p>There is also a default implementation available, which will dump the stacks of all {@link Thread Threads}
26+
* to {@code System.err}. This default implementation need to be enabled with the jupiter property:
27+
* {@code junit.jupiter.execution.timeout.threaddump.enabled}
28+
*
29+
*
30+
* @since 5.12
31+
* @see org.junit.jupiter.api.Timeout
32+
*/
33+
@API(status = EXPERIMENTAL, since = "5.12")
34+
public interface PreInterruptCallback extends Extension {
35+
36+
/**
37+
* Callback that is invoked <em>before</em> a {@link Thread} is interrupted with {@link Thread#interrupt()}.
38+
*
39+
* <p>Caution: There is no guarantee on which {@link Thread} this callback will be executed.</p>
40+
*
41+
* @param threadToInterrupt the target {@link Thread}, which will get interrupted.
42+
* @param context the current extension context; never {@code null}
43+
*/
44+
void beforeThreadInterrupt(Thread threadToInterrupt, ExtensionContext context) throws Exception;
45+
}

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ public final class Constants {
108108
*/
109109
public static final String EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME;
110110

111+
/**
112+
* Property name used to enable the default behavior of {@link org.junit.jupiter.api.extension.PreInterruptCallback}
113+
* extension to print the stacks of all {@link Thread}s to {@code System.err} before the test is interrupted.
114+
*
115+
* <p>The default behavior is not to enable the dump fo threads.
116+
*
117+
* @since 5.12
118+
*/
119+
@API(status = EXPERIMENTAL, since = "5.12")
120+
public static final String EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME;
121+
111122
/**
112123
* Property name used to set the default test instance lifecycle mode: {@value}
113124
*
@@ -192,7 +203,6 @@ public final class Constants {
192203
* <p>When set to {@code false} the underlying fork-join pool will reject
193204
* additional tasks if all available workers are busy and the maximum
194205
* pool-size would be exceeded.
195-
196206
* <p>Value must either {@code true} or {@code false}; defaults to {@code true}.
197207
*
198208
* <p>Note: This property only takes affect on Java 9+.

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ public boolean isExtensionAutoDetectionEnabled() {
6868
__ -> delegate.isExtensionAutoDetectionEnabled());
6969
}
7070

71+
@Override
72+
public boolean isExtensionTimeoutThreadDumpEnabled() {
73+
return (boolean) cache.computeIfAbsent(EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME,
74+
__ -> delegate.isExtensionTimeoutThreadDumpEnabled());
75+
}
76+
7177
@Override
7278
public ExecutionMode getDefaultExecutionMode() {
7379
return (ExecutionMode) cache.computeIfAbsent(DEFAULT_EXECUTION_MODE_PROPERTY_NAME,

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ public boolean isExtensionAutoDetectionEnabled() {
9393
return configurationParameters.getBoolean(EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME).orElse(false);
9494
}
9595

96+
@Override
97+
public boolean isExtensionTimeoutThreadDumpEnabled() {
98+
return configurationParameters.getBoolean(EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME).orElse(false);
99+
}
100+
96101
@Override
97102
public ExecutionMode getDefaultExecutionMode() {
98103
return executionModeConverter.get(configurationParameters, DEFAULT_EXECUTION_MODE_PROPERTY_NAME,

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public interface JupiterConfiguration {
4040
String DEFAULT_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_EXECUTION_MODE_PROPERTY_NAME;
4141
String DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME = Execution.DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME;
4242
String EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME = "junit.jupiter.extensions.autodetection.enabled";
43+
String EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME = "junit.jupiter.execution.timeout.threaddump.enabled";
4344
String DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME = TestInstance.Lifecycle.DEFAULT_LIFECYCLE_PROPERTY_NAME;
4445
String DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME = DisplayNameGenerator.DEFAULT_GENERATOR_PROPERTY_NAME;
4546
String DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME = MethodOrderer.DEFAULT_ORDER_PROPERTY_NAME;
@@ -54,6 +55,8 @@ public interface JupiterConfiguration {
5455

5556
boolean isExtensionAutoDetectionEnabled();
5657

58+
boolean isExtensionTimeoutThreadDumpEnabled();
59+
5760
ExecutionMode getDefaultExecutionMode();
5861

5962
ExecutionMode getDefaultClassesExecutionMode();

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,20 @@
1515

1616
import java.util.Collections;
1717
import java.util.LinkedHashSet;
18+
import java.util.List;
1819
import java.util.Map;
1920
import java.util.Optional;
2021
import java.util.Set;
2122
import java.util.function.Function;
2223

2324
import org.junit.jupiter.api.extension.ExecutableInvoker;
25+
import org.junit.jupiter.api.extension.Extension;
2426
import org.junit.jupiter.api.extension.ExtensionContext;
2527
import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource;
2628
import org.junit.jupiter.api.parallel.ExecutionMode;
2729
import org.junit.jupiter.engine.config.JupiterConfiguration;
2830
import org.junit.jupiter.engine.execution.NamespaceAwareStore;
31+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
2932
import org.junit.platform.commons.JUnitException;
3033
import org.junit.platform.commons.util.Preconditions;
3134
import org.junit.platform.engine.EngineExecutionListener;
@@ -53,9 +56,10 @@ abstract class AbstractExtensionContext<T extends TestDescriptor> implements Ext
5356
private final JupiterConfiguration configuration;
5457
private final NamespacedHierarchicalStore<Namespace> valuesStore;
5558
private final ExecutableInvoker executableInvoker;
59+
private final ExtensionRegistry extensionRegistry;
5660

5761
AbstractExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, T testDescriptor,
58-
JupiterConfiguration configuration,
62+
JupiterConfiguration configuration, ExtensionRegistry extensionRegistry,
5963
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
6064
this.executableInvoker = executableInvokerFactory.apply(this);
6165

@@ -67,6 +71,7 @@ abstract class AbstractExtensionContext<T extends TestDescriptor> implements Ext
6771
this.testDescriptor = testDescriptor;
6872
this.configuration = configuration;
6973
this.valuesStore = createStore(parent);
74+
this.extensionRegistry = extensionRegistry;
7075

7176
// @formatter:off
7277
this.tags = testDescriptor.getTags().stream()
@@ -152,6 +157,14 @@ public ExecutableInvoker getExecutableInvoker() {
152157
return executableInvoker;
153158
}
154159

160+
@Override
161+
public <E extends Extension> List<E> getExtensions(Class<E> extensionType) {
162+
if (extensionRegistry == null) {
163+
return Collections.emptyList();
164+
}
165+
return extensionRegistry.getExtensions(extensionType);
166+
}
167+
155168
protected abstract Node.ExecutionMode getPlatformExecutionMode();
156169

157170
private ExecutionMode toJupiterExecutionMode(Node.ExecutionMode mode) {

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext conte
181181

182182
ThrowableCollector throwableCollector = createThrowableCollector();
183183
ClassExtensionContext extensionContext = new ClassExtensionContext(context.getExtensionContext(),
184-
context.getExecutionListener(), this, this.lifecycle, context.getConfiguration(), throwableCollector,
185-
it -> new DefaultExecutableInvoker(it, registry));
184+
context.getExecutionListener(), this, this.lifecycle, context.getConfiguration(),
185+
context.getExtensionRegistry(), throwableCollector, it -> new DefaultExecutableInvoker(it, registry));
186186

187187
// @formatter:off
188188
return context.extend()

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.junit.jupiter.api.extension.ExtensionContext;
2121
import org.junit.jupiter.api.extension.TestInstances;
2222
import org.junit.jupiter.engine.config.JupiterConfiguration;
23+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
2324
import org.junit.platform.engine.EngineExecutionListener;
2425
import org.junit.platform.engine.support.hierarchical.Node;
2526
import org.junit.platform.engine.support.hierarchical.ThrowableCollector;
@@ -39,23 +40,24 @@ final class ClassExtensionContext extends AbstractExtensionContext<ClassBasedTes
3940
* Create a new {@code ClassExtensionContext} with {@link Lifecycle#PER_METHOD}.
4041
*
4142
* @see #ClassExtensionContext(ExtensionContext, EngineExecutionListener, ClassBasedTestDescriptor,
42-
* Lifecycle, JupiterConfiguration, ThrowableCollector, Function)
43+
* Lifecycle, JupiterConfiguration, ExtensionRegistry, ThrowableCollector, Function)
4344
*/
4445
ClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
4546
ClassBasedTestDescriptor testDescriptor, JupiterConfiguration configuration,
46-
ThrowableCollector throwableCollector,
47+
ExtensionRegistry extensionRegistry, ThrowableCollector throwableCollector,
4748
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
4849

49-
this(parent, engineExecutionListener, testDescriptor, Lifecycle.PER_METHOD, configuration, throwableCollector,
50-
executableInvokerFactory);
50+
this(parent, engineExecutionListener, testDescriptor, Lifecycle.PER_METHOD, configuration, extensionRegistry,
51+
throwableCollector, executableInvokerFactory);
5152
}
5253

5354
ClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
5455
ClassBasedTestDescriptor testDescriptor, Lifecycle lifecycle, JupiterConfiguration configuration,
55-
ThrowableCollector throwableCollector,
56+
ExtensionRegistry extensionRegistry, ThrowableCollector throwableCollector,
5657
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
5758

58-
super(parent, engineExecutionListener, testDescriptor, configuration, executableInvokerFactory);
59+
super(parent, engineExecutionListener, testDescriptor, configuration, extensionRegistry,
60+
executableInvokerFactory);
5961

6062
this.lifecycle = lifecycle;
6163
this.throwableCollector = throwableCollector;

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicExtensionContext.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,18 @@
2020
import org.junit.jupiter.api.extension.ExtensionContext;
2121
import org.junit.jupiter.api.extension.TestInstances;
2222
import org.junit.jupiter.engine.config.JupiterConfiguration;
23+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
2324
import org.junit.platform.engine.EngineExecutionListener;
2425
import org.junit.platform.engine.support.hierarchical.Node;
2526

2627
class DynamicExtensionContext extends AbstractExtensionContext<DynamicNodeTestDescriptor> {
2728

2829
DynamicExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
2930
DynamicNodeTestDescriptor testDescriptor, JupiterConfiguration configuration,
31+
ExtensionRegistry extensionRegistry,
3032
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
31-
super(parent, engineExecutionListener, testDescriptor, configuration, executableInvokerFactory);
33+
super(parent, engineExecutionListener, testDescriptor, configuration, extensionRegistry,
34+
executableInvokerFactory);
3235
}
3336

3437
@Override

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicNodeTestDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public String getLegacyReportingName() {
4646
@Override
4747
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) {
4848
DynamicExtensionContext extensionContext = new DynamicExtensionContext(context.getExtensionContext(),
49-
context.getExecutionListener(), this, context.getConfiguration(),
49+
context.getExecutionListener(), this, context.getConfiguration(), context.getExtensionRegistry(),
5050
it -> new DefaultExecutableInvoker(it, context.getExtensionRegistry()));
5151
// @formatter:off
5252
return context.extend()

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineDescriptor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext conte
5353
context.getConfiguration());
5454
EngineExecutionListener executionListener = context.getExecutionListener();
5555
ExtensionContext extensionContext = new JupiterEngineExtensionContext(executionListener, this,
56-
context.getConfiguration(), it -> new DefaultExecutableInvoker(it, extensionRegistry));
56+
context.getConfiguration(), context.getExtensionRegistry(),
57+
it -> new DefaultExecutableInvoker(it, extensionRegistry));
5758

5859
// @formatter:off
5960
return context.extend()

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterEngineExtensionContext.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.junit.jupiter.api.extension.ExtensionContext;
2121
import org.junit.jupiter.api.extension.TestInstances;
2222
import org.junit.jupiter.engine.config.JupiterConfiguration;
23+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
2324
import org.junit.platform.engine.EngineExecutionListener;
2425
import org.junit.platform.engine.support.hierarchical.Node;
2526

@@ -30,9 +31,11 @@ final class JupiterEngineExtensionContext extends AbstractExtensionContext<Jupit
3031

3132
JupiterEngineExtensionContext(EngineExecutionListener engineExecutionListener,
3233
JupiterEngineDescriptor testDescriptor, JupiterConfiguration configuration,
34+
ExtensionRegistry extensionRegistry,
3335
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
3436

35-
super(null, engineExecutionListener, testDescriptor, configuration, executableInvokerFactory);
37+
super(null, engineExecutionListener, testDescriptor, configuration, extensionRegistry,
38+
executableInvokerFactory);
3639
}
3740

3841
@Override

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.junit.jupiter.api.extension.ExtensionContext;
2121
import org.junit.jupiter.api.extension.TestInstances;
2222
import org.junit.jupiter.engine.config.JupiterConfiguration;
23+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
2324
import org.junit.platform.engine.EngineExecutionListener;
2425
import org.junit.platform.engine.support.hierarchical.Node;
2526
import org.junit.platform.engine.support.hierarchical.ThrowableCollector;
@@ -35,10 +36,11 @@ final class MethodExtensionContext extends AbstractExtensionContext<TestMethodTe
3536

3637
MethodExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
3738
TestMethodTestDescriptor testDescriptor, JupiterConfiguration configuration,
38-
ThrowableCollector throwableCollector,
39+
ExtensionRegistry extensionRegistry, ThrowableCollector throwableCollector,
3940
Function<ExtensionContext, ExecutableInvoker> executableInvokerFactory) {
4041

41-
super(parent, engineExecutionListener, testDescriptor, configuration, executableInvokerFactory);
42+
super(parent, engineExecutionListener, testDescriptor, configuration, extensionRegistry,
43+
executableInvokerFactory);
4244

4345
this.throwableCollector = throwableCollector;
4446
}

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext conte
9999
MutableExtensionRegistry registry = populateNewExtensionRegistry(context);
100100
ThrowableCollector throwableCollector = createThrowableCollector();
101101
MethodExtensionContext extensionContext = new MethodExtensionContext(context.getExtensionContext(),
102-
context.getExecutionListener(), this, context.getConfiguration(), throwableCollector,
103-
it -> new DefaultExecutableInvoker(it, registry));
102+
context.getExecutionListener(), this, context.getConfiguration(), context.getExtensionRegistry(),
103+
throwableCollector, it -> new DefaultExecutableInvoker(it, registry));
104104
// @formatter:off
105105
JupiterEngineExecutionContext newContext = context.extend()
106106
.withExtensionRegistry(registry)

0 commit comments

Comments
 (0)