Skip to content

Commit 44dfb8a

Browse files
committed
Add tests
Issue #4434
1 parent 5c7b99e commit 44dfb8a

File tree

3 files changed

+110
-11
lines changed

3 files changed

+110
-11
lines changed

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

+14-10
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ default <V> V getOrDefault(Object key, Class<V> requiredType, V defaultValue) {
598598
* further details.
599599
*
600600
* <p>If {@code type} implements {@link ExtensionContext.Store.CloseableResource}
601-
* the {@code close()} method will be invoked on the stored object when
601+
* or {@link AutoCloseable} the {@code close()} method will be invoked on the stored object when
602602
* the store is closed.
603603
*
604604
* @param type the type of object to retrieve; never {@code null}
@@ -608,6 +608,7 @@ default <V> V getOrDefault(Object key, Class<V> requiredType, V defaultValue) {
608608
* @see #getOrComputeIfAbsent(Object, Function)
609609
* @see #getOrComputeIfAbsent(Object, Function, Class)
610610
* @see CloseableResource
611+
* @see AutoCloseable
611612
*/
612613
@API(status = STABLE, since = "5.1")
613614
default <V> V getOrComputeIfAbsent(Class<V> type) {
@@ -628,7 +629,7 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
628629
* {@link #getOrComputeIfAbsent(Object, Function, Class)} instead.
629630
*
630631
* <p>If the created value is an instance of {@link ExtensionContext.Store.CloseableResource}
631-
* the {@code close()} method will be invoked on the stored object when
632+
* or {@link AutoCloseable} the {@code close()} method will be invoked on the stored object when
632633
* the store is closed.
633634
*
634635
* @param key the key; never {@code null}
@@ -640,6 +641,7 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
640641
* @see #getOrComputeIfAbsent(Class)
641642
* @see #getOrComputeIfAbsent(Object, Function, Class)
642643
* @see CloseableResource
644+
* @see AutoCloseable
643645
*/
644646
<K, V> Object getOrComputeIfAbsent(K key, Function<K, V> defaultCreator);
645647

@@ -655,8 +657,8 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
655657
* the {@code key} as input), stored, and returned.
656658
*
657659
* <p>If {@code requiredType} implements {@link ExtensionContext.Store.CloseableResource}
658-
* the {@code close()} method will be invoked on the stored object when
659-
* the store is closed.
660+
* or {@link AutoCloseable} the {@code close()} method will be invoked on the stored
661+
* object when the store is closed.
660662
*
661663
* @param key the key; never {@code null}
662664
* @param defaultCreator the function called with the supplied {@code key}
@@ -668,6 +670,7 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
668670
* @see #getOrComputeIfAbsent(Class)
669671
* @see #getOrComputeIfAbsent(Object, Function)
670672
* @see CloseableResource
673+
* @see AutoCloseable
671674
*/
672675
<K, V> V getOrComputeIfAbsent(K key, Function<K, V> defaultCreator, Class<V> requiredType);
673676

@@ -679,22 +682,23 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
679682
* overwrite it.
680683
*
681684
* <p>If the {@code value} is an instance of {@link ExtensionContext.Store.CloseableResource}
682-
* the {@code close()} method will be invoked on the stored object when
683-
* the store is closed.
685+
* or {@link AutoCloseable} the {@code close()} method will be invoked on the stored
686+
* object when the store is closed.
684687
*
685688
* @param key the key under which the value should be stored; never
686689
* {@code null}
687690
* @param value the value to store; may be {@code null}
688691
* @see CloseableResource
692+
* @see AutoCloseable
689693
*/
690694
void put(Object key, Object value);
691695

692696
/**
693697
* Remove the value that was previously stored under the supplied {@code key}.
694698
*
695699
* <p>The value will only be removed in the current {@link ExtensionContext},
696-
* not in ancestors. In addition, the {@link CloseableResource} API will not
697-
* be honored for values that are manually removed via this method.
700+
* not in ancestors. In addition, the {@link CloseableResource} and {@link AutoCloseable}
701+
* API will not be honored for values that are manually removed via this method.
698702
*
699703
* <p>For greater type safety, consider using {@link #remove(Object, Class)}
700704
* instead.
@@ -711,8 +715,8 @@ default <V> V getOrComputeIfAbsent(Class<V> type) {
711715
* under the supplied {@code key}.
712716
*
713717
* <p>The value will only be removed in the current {@link ExtensionContext},
714-
* not in ancestors. In addition, the {@link CloseableResource} API will not
715-
* be honored for values that are manually removed via this method.
718+
* not in ancestors. In addition, the {@link CloseableResource} and {@link AutoCloseable}
719+
* API will not be honored for values that are manually removed via this method.
716720
*
717721
* @param key the key; never {@code null}
718722
* @param requiredType the required type of the value; never {@code null}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.junit.jupiter.api.extension.ExecutableInvoker;
2828
import org.junit.jupiter.api.extension.Extension;
2929
import org.junit.jupiter.api.extension.ExtensionContext;
30-
import org.junit.jupiter.api.extension.ExtensionContext.Store;
3130
import org.junit.jupiter.api.extension.MediaType;
3231
import org.junit.jupiter.api.function.ThrowingConsumer;
3332
import org.junit.jupiter.api.parallel.ExecutionMode;
@@ -89,6 +88,7 @@ abstract class AbstractExtensionContext<T extends TestDescriptor> implements Ext
8988
CLOSE_RESOURCES = (__, ___, value) -> {
9089
if (value instanceof Store.CloseableResource) {
9190
((Store.CloseableResource) value).close();
91+
return;
9292
}
9393

9494
boolean isAutoCloseEnabled = configuration.isAutoCloseEnabled();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright 2015-2025 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.engine.descriptor;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
import static org.mockito.Mockito.mock;
15+
import static org.mockito.Mockito.when;
16+
17+
import org.junit.jupiter.api.BeforeEach;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.extension.BeforeAllCallback;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
import org.junit.jupiter.api.extension.ExtensionContext;
22+
import org.junit.jupiter.engine.config.JupiterConfiguration;
23+
import org.junit.jupiter.engine.extension.ExtensionRegistry;
24+
import org.junit.platform.launcher.core.NamespacedHierarchicalStoreProviders;
25+
26+
class ResourceAutoClosingTests {
27+
28+
private final JupiterConfiguration configuration = mock();
29+
private final ExtensionRegistry extensionRegistry = mock();
30+
private final JupiterEngineDescriptor testDescriptor = mock();
31+
private final LauncherStoreFacade launcherStoreFacade = new LauncherStoreFacade(
32+
NamespacedHierarchicalStoreProviders.dummyNamespacedHierarchicalStore());
33+
34+
@BeforeEach
35+
void setUp() {
36+
when(testDescriptor.getConfiguration()).thenReturn(configuration);
37+
}
38+
39+
@Test
40+
void shouldCloseAutoCloseableWhenAutoCloseEnabledIsTrue() throws Exception {
41+
AutoCloseableResource resource = new AutoCloseableResource();
42+
when(configuration.isAutoCloseEnabled()).thenReturn(true);
43+
44+
ExtensionContext extensionContext = new JupiterEngineExtensionContext(null, testDescriptor, configuration,
45+
extensionRegistry, launcherStoreFacade);
46+
ExtensionContext.Store store = extensionContext.getStore(ExtensionContext.StoreScope.EXECUTION_REQUEST,
47+
ExtensionContext.Namespace.GLOBAL);
48+
store.put("resource", resource);
49+
50+
((AutoCloseable) extensionContext).close();
51+
52+
assertThat(resource.closed).isTrue();
53+
}
54+
55+
@Test
56+
void shouldNotCloseAutoCloseableWhenAutoCloseEnabledIsFalse() throws Exception {
57+
AutoCloseableResource resource = new AutoCloseableResource();
58+
when(configuration.isAutoCloseEnabled()).thenReturn(false);
59+
ExtensionContext extensionContext = new JupiterEngineExtensionContext(null, testDescriptor, configuration,
60+
extensionRegistry, launcherStoreFacade);
61+
62+
ExtensionContext.Store store = extensionContext.getStore(ExtensionContext.StoreScope.EXECUTION_REQUEST,
63+
ExtensionContext.Namespace.GLOBAL);
64+
store.put("resource", resource);
65+
66+
((AutoCloseable) extensionContext).close();
67+
68+
assertThat(resource.closed).isFalse();
69+
}
70+
71+
static class AutoCloseableResource implements AutoCloseable {
72+
private boolean closed = false;
73+
74+
@Override
75+
public void close() {
76+
closed = true;
77+
}
78+
}
79+
80+
static class AutoCloseableResourceStoreUsingExtension implements BeforeAllCallback {
81+
@Override
82+
public void beforeAll(ExtensionContext context) {
83+
var store = context.getStore(ExtensionContext.Namespace.GLOBAL);
84+
store.put("resource", new AutoCloseableResource());
85+
}
86+
}
87+
88+
@SuppressWarnings("JUnitMalformedDeclaration")
89+
@ExtendWith(AutoCloseableResourceStoreUsingExtension.class)
90+
static class AutoCloseableTestCase {
91+
@Test
92+
void dummyTest() {
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)