diff --git a/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionContextTests.java b/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionContextTests.java
index 07bf6d063d77..62153c99bf81 100644
--- a/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionContextTests.java
+++ b/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionContextTests.java
@@ -122,45 +122,25 @@ public void reportEntriesArePublishedToExecutionContext() {
}
@Test
- public void storingAttributesWithDefaultNamespace() {
+ public void usingStore() {
MethodTestDescriptor methodTestDescriptor = methodDescriptor();
ClassTestDescriptor classTestDescriptor = outerClassDescriptor(methodTestDescriptor);
ExtensionContext parentContext = new ClassBasedContainerExtensionContext(null, null, classTestDescriptor);
MethodBasedTestExtensionContext childContext = new MethodBasedTestExtensionContext(parentContext, null,
methodTestDescriptor, new OuterClass());
- childContext.put("a key", "a value");
- assertEquals("a value", childContext.get("a key"));
+ ExtensionContext.Store store = childContext.getStore();
- assertEquals("other value", childContext.getOrComputeIfAbsent("other key", key -> "other value"));
+ store.put("a key", "a value");
+ assertEquals("a value", store.get("a key"));
- childContext.remove("a key");
- assertNull(childContext.get("a key"));
+ assertEquals("other value", store.getOrComputeIfAbsent("other key", key -> "other value"));
- parentContext.put("parent key", "parent value");
- assertEquals("parent value", childContext.get("parent key"));
- }
-
- @Test
- public void storingAttributesWithNamespace() {
- MethodTestDescriptor methodTestDescriptor = methodDescriptor();
- ClassTestDescriptor classTestDescriptor = outerClassDescriptor(methodTestDescriptor);
- ExtensionContext parentContext = new ClassBasedContainerExtensionContext(null, null, classTestDescriptor);
- MethodBasedTestExtensionContext childContext = new MethodBasedTestExtensionContext(parentContext, null,
- methodTestDescriptor, new OuterClass());
-
- String namespace = "a namespace";
-
- childContext.put("a key", "a value", namespace);
- assertEquals("a value", childContext.get("a key", namespace));
-
- assertEquals("other value", childContext.getOrComputeIfAbsent("other key", key -> "other value"), namespace);
-
- childContext.remove("a key", namespace);
- assertNull(childContext.get("a key", namespace));
+ assertEquals("a value", store.remove("a key"));
+ assertNull(store.get("a key"));
- parentContext.put("parent key", "parent value", namespace);
- assertEquals("parent value", childContext.get("parent key", namespace));
+ store.put("parent key", "parent value");
+ assertEquals("parent value", store.get("parent key"));
}
private ClassTestDescriptor nestedClassDescriptor() {
diff --git a/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionValuesStoreTest.java b/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionValuesStoreTest.java
index 7bd154a121e0..0b2efd466d1d 100644
--- a/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionValuesStoreTest.java
+++ b/junit-tests/src/test/java/org/junit/gen5/engine/junit5/descriptor/ExtensionValuesStoreTest.java
@@ -15,7 +15,7 @@
import org.junit.gen5.api.BeforeEach;
import org.junit.gen5.api.Nested;
import org.junit.gen5.api.Test;
-import org.junit.gen5.engine.junit5.descriptor.ExtensionValuesStore.Namespace;
+import org.junit.gen5.api.extension.ExtensionContext.*;
/**
* Microtests for {@link ExtensionValuesStore}
@@ -29,6 +29,8 @@ class ExtensionValuesStoreTests {
private Object value = createObject("value");
+ private Namespace namespace = Namespace.of("ns");
+
@BeforeEach
void initializeStore() {
parentStore = new ExtensionValuesStore();
@@ -36,59 +38,102 @@ void initializeStore() {
}
@Nested
- class UsingDefaultNamespaceTests {
+ class StoringValuesTests {
@Test
void getWithUnknownKeyReturnsNull() {
- assertNull(store.get("unknown key"));
+ assertNull(store.get(namespace, "unknown key"));
}
@Test
void putAndGetWithSameKey() {
- store.put(key, value);
- assertEquals(value, store.get(key));
+ store.put(namespace, key, value);
+ assertEquals(value, store.get(namespace, key));
}
@Test
void valueCanBeReplaced() {
- store.put(key, value);
+ store.put(namespace, key, value);
Object newValue = new Object();
- store.put(key, newValue);
+ store.put(namespace, key, newValue);
- assertEquals(newValue, store.get(key));
+ assertEquals(newValue, store.get(namespace, key));
}
@Test
void valueIsComputedIfAbsent() {
- assertEquals(value, store.getOrComputeIfAbsent(key, innerKey -> value));
- assertEquals(value, store.get(key));
+ assertEquals(value, store.getOrComputeIfAbsent(namespace, key, innerKey -> value));
+ assertEquals(value, store.get(namespace, key));
}
@Test
void valueIsNotComputedIfPresent() {
- store.put(key, value);
+ store.put(namespace, key, value);
- assertEquals(value, store.getOrComputeIfAbsent(key, innerKey -> "a different value"));
- assertEquals(value, store.get(key));
+ assertEquals(value, store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value"));
+ assertEquals(value, store.get(namespace, key));
}
@Test
void nullIsAValidValueToPut() {
- store.put(key, null);
+ store.put(namespace, key, null);
- assertEquals(null, store.getOrComputeIfAbsent(key, innerKey -> "a different value"));
- assertEquals(null, store.get(key));
+ assertEquals(null, store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value"));
+ assertEquals(null, store.get(namespace, key));
}
@Test
void keysCanBeRemoved() {
- store.put(key, value);
- store.remove(key);
+ store.put(namespace, key, value);
+ assertEquals(value, store.remove(namespace, key));
- assertNull(store.get(key));
- assertEquals("a different value", store.getOrComputeIfAbsent(key, innerKey -> "a different value"));
+ assertNull(store.get(namespace, key));
+ assertEquals("a different value",
+ store.getOrComputeIfAbsent(namespace, key, innerKey -> "a different value"));
+ }
+
+ @Test
+ void sameKeyWithDifferentNamespaces() {
+ Object value1 = createObject("value1");
+ Namespace namespace1 = Namespace.of("ns1");
+
+ Object value2 = createObject("value2");
+ Namespace namespace2 = Namespace.of("ns2");
+
+ store.put(namespace1, key, value1);
+ store.put(namespace2, key, value2);
+
+ assertEquals(value1, store.get(namespace1, key));
+ assertEquals(value2, store.get(namespace2, key));
+ }
+
+ @Test
+ void valueIsComputedIfAbsentInDifferentNamespace() {
+ Namespace namespace1 = Namespace.of("ns1");
+ Namespace namespace2 = Namespace.of("ns2");
+
+ assertEquals(value, store.getOrComputeIfAbsent(namespace1, key, innerKey -> value));
+ assertEquals(value, store.get(namespace1, key));
+
+ assertNull(store.get(namespace2, key));
+ }
+
+ @Test
+ void keyIsOnlyRemovedInGivenNamespace() {
+ Namespace namespace1 = Namespace.of("ns1");
+ Namespace namespace2 = Namespace.of("ns2");
+
+ Object value1 = createObject("value1");
+ Object value2 = createObject("value2");
+
+ store.put(namespace1, key, value1);
+ store.put(namespace2, key, value2);
+ store.remove(namespace1, key);
+
+ assertNull(store.get(namespace1, key));
+ assertEquals(value2, store.get(namespace2, key));
}
}
@@ -98,60 +143,52 @@ class InheritedValuesTests {
@Test
void valueFromParentIsVisible() {
- parentStore.put(key, value);
- assertEquals(value, store.get(key));
+ parentStore.put(namespace, key, value);
+ assertEquals(value, store.get(namespace, key));
}
@Test
void valueFromParentCanBeOverriddenInChild() {
- parentStore.put(key, value);
+ parentStore.put(namespace, key, value);
Object otherValue = new Object();
- store.put(key, otherValue);
- assertEquals(otherValue, store.get(key));
+ store.put(namespace, key, otherValue);
+ assertEquals(otherValue, store.get(namespace, key));
- assertEquals(value, parentStore.get(key));
+ assertEquals(value, parentStore.get(namespace, key));
}
}
@Nested
- class UsingExplicitNamespaceTests {
+ class CompositNamespaceTests {
@Test
- void sameKeyWithDifferentNamespaces() {
- Object value1 = createObject("value1");
- Namespace namespace1 = Namespace.sharedWith("ns1");
+ void additionNamespacePartMakesADifferenc() {
+
+ Namespace ns1 = Namespace.of("part1", "part2");
+ Namespace ns2 = Namespace.of("part1");
+ Namespace ns3 = Namespace.of("part1", "part2");
Object value2 = createObject("value2");
- Namespace namespace2 = Namespace.sharedWith("ns2");
- store.put(key, value1, namespace1);
- store.put(key, value2, namespace2);
+ parentStore.put(ns1, key, value);
+ parentStore.put(ns2, key, value2);
- assertEquals(value1, store.get(key, namespace1));
- assertEquals(value2, store.get(key, namespace2));
+ assertEquals(value, store.get(ns1, key));
+ assertEquals(value, store.get(ns3, key));
+ assertEquals(value2, store.get(ns2, key));
}
@Test
- void valueIsComputedIfAbsentInDifferentNamespace() {
- Namespace namespace = Namespace.sharedWith("ns");
- assertEquals(value, store.getOrComputeIfAbsent(key, innerKey -> value, namespace));
- assertEquals(value, store.get(key, namespace));
+ void orderOfNamespacePartsDoesNotMatter() {
- assertNull(store.get(key));
- }
-
- @Test
- void keyIsOnlyRemovedInGivenNamespace() {
- Namespace namespace = Namespace.sharedWith("ns");
- Object valueInNamespace = createObject("valueInNamespace");
+ Namespace ns1 = Namespace.of("part1", "part2");
+ Namespace ns2 = Namespace.of("part2", "part1");
- store.put(key, value);
- store.put(key, valueInNamespace, namespace);
- store.remove(key, namespace);
+ parentStore.put(ns1, key, value);
- assertNull(store.get(key, namespace));
- assertEquals(value, store.get(key));
+ assertEquals(value, store.get(ns1, key));
+ assertEquals(value, store.get(ns2, key));
}
}
diff --git a/junit5-api/src/main/java/org/junit/gen5/api/extension/ExtensionContext.java b/junit5-api/src/main/java/org/junit/gen5/api/extension/ExtensionContext.java
index 8841dab880a2..5b4220aa8d61 100644
--- a/junit5-api/src/main/java/org/junit/gen5/api/extension/ExtensionContext.java
+++ b/junit5-api/src/main/java/org/junit/gen5/api/extension/ExtensionContext.java
@@ -11,10 +11,15 @@
package org.junit.gen5.api.extension;
import java.lang.reflect.AnnotatedElement;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Function;
+import org.junit.gen5.commons.util.Preconditions;
+
/**
* {@code ExtensionContext} encapsulates the context in which the
* current test or container is being executed.
@@ -55,82 +60,6 @@ public interface ExtensionContext {
AnnotatedElement getElement();
- // Storing methods.
-
- /**
- * Get an object that has been stored using a {@code key}
- *
- * @param key the key
- * @return the value
- */
- Object get(Object key);
-
- /**
- * Store a {@code value} for later retrieval using a {@code key}. {@code null} is a valid value.
- *
- * @param key the key
- * @param value the value
- */
- void put(Object key, Object value);
-
- /**
- * Get an object that has been stored using a {@code key}. If no value has been store using that {@code key}
- * the value will be computed by the {@code defaultCreator} and be stored.
- *
- * @param key the key
- * @param defaultCreator the function called to create the value
- * @return the value
- */
- Object getOrComputeIfAbsent(Object key, Function