1111import java .util .concurrent .ConcurrentLinkedDeque ;
1212import org .junit .jupiter .api .extension .AfterAllCallback ;
1313import org .junit .jupiter .api .extension .AfterEachCallback ;
14+ import org .junit .jupiter .api .extension .BeforeAllCallback ;
1415import org .junit .jupiter .api .extension .ExtensionContext ;
1516
1617/**
2122 * <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
2223 * at any time.
2324 */
24- public class AutoCleanupExtension implements AfterEachCallback , AfterAllCallback {
25+ public class AutoCleanupExtension
26+ implements BeforeAllCallback , AfterEachCallback , AfterAllCallback {
2527 private final Deque <AutoCloseable > thingsToCleanUp = new ConcurrentLinkedDeque <>();
2628 private final Deque <AutoCloseable > thingsToCleanUpAfterAll = new ConcurrentLinkedDeque <>();
29+ // Tracks the first (outermost) container the extension is registered in, so that afterAll only
30+ // runs deferAfterAll cleanups once — not once per @Nested container.
31+ private volatile ExtensionContext rootContext ;
2732
2833 public static AutoCleanupExtension create () {
2934 return new AutoCleanupExtension ();
@@ -41,6 +46,13 @@ public void deferAfterAll(AutoCloseable cleanupAction) {
4146 thingsToCleanUpAfterAll .push (cleanupAction );
4247 }
4348
49+ @ Override
50+ public void beforeAll (ExtensionContext extensionContext ) {
51+ if (rootContext == null ) {
52+ rootContext = extensionContext ;
53+ }
54+ }
55+
4456 @ Override
4557 public void afterEach (ExtensionContext extensionContext ) throws Exception {
4658 List <Exception > exceptions = new ArrayList <>();
@@ -56,6 +68,11 @@ public void afterEach(ExtensionContext extensionContext) throws Exception {
5668
5769 @ Override
5870 public void afterAll (ExtensionContext extensionContext ) throws Exception {
71+ // afterAll fires once per container the extension is registered in, including each @Nested
72+ // class. Only run deferAfterAll cleanups when the outermost container completes.
73+ if (extensionContext != rootContext ) {
74+ return ;
75+ }
5976 List <Exception > exceptions = new ArrayList <>();
6077 while (!thingsToCleanUpAfterAll .isEmpty ()) {
6178 try {
0 commit comments