Skip to content

Commit 2ab3370

Browse files
sbrannenmarcphilipp
authored andcommitted
Improve documentation for TestInstantiationAwareExtension
This commit improves the documentation for TestInstantiationAwareExtension and raises awareness of semantic differences by introducing class-level notes the Javadoc for all affected extension APIs. Closes #5107
1 parent 0b9617e commit 2ab3370

File tree

6 files changed

+150
-54
lines changed

6 files changed

+150
-54
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@
4545
* <p>Consult the documentation in {@link Extension} for details on
4646
* constructor requirements.
4747
*
48+
* <h2>{@code ExtensionContext} Scope</h2>
49+
*
50+
* <p>As of JUnit Jupiter 5.12, this API participates in the
51+
* {@link TestInstantiationAwareExtension} contract. Implementations of this API
52+
* may therefore choose to override
53+
* {@link TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
54+
* getTestInstantiationExtensionContextScope(ExtensionContext)}. See
55+
* {@link #interceptTestClassConstructor(Invocation, ReflectiveInvocationContext, ExtensionContext)}
56+
* for details.
57+
*
4858
* @since 5.5
4959
* @see Invocation
5060
* @see ReflectiveInvocationContext

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@
4747
* <p>Consult the documentation in {@link Extension} for details on
4848
* constructor requirements.
4949
*
50+
* <h2>{@code ExtensionContext} Scope</h2>
51+
*
52+
* <p>As of JUnit Jupiter 5.12, this API participates in the
53+
* {@link TestInstantiationAwareExtension} contract. Implementations of this API
54+
* may therefore choose to override
55+
* {@link TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
56+
* getTestInstantiationExtensionContextScope(ExtensionContext)} to require a
57+
* test-method scoped {@code ExtensionContext}.
58+
*
5059
* @since 5.0
5160
* @see #supportsParameter(ParameterContext, ExtensionContext)
5261
* @see #resolveParameter(ParameterContext, ExtensionContext)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@
4343
* <p>Consult the documentation in {@link Extension} for details on
4444
* constructor requirements.
4545
*
46+
* <h2>{@code ExtensionContext} Scope</h2>
47+
*
48+
* <p>As of JUnit Jupiter 5.12, this API participates in the
49+
* {@link TestInstantiationAwareExtension} contract. Implementations of this API
50+
* may therefore choose to override
51+
* {@link TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
52+
* getTestInstantiationExtensionContextScope(ExtensionContext)} to require a
53+
* test-method scoped {@code ExtensionContext}. See
54+
* {@link #createTestInstance(TestInstanceFactoryContext, ExtensionContext)} for
55+
* further details.
56+
*
4657
* @since 5.3
4758
* @see #createTestInstance(TestInstanceFactoryContext, ExtensionContext)
4859
* @see TestInstanceFactoryContext

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
* <p>Consult the documentation in {@link Extension} for details on
3434
* constructor requirements.
3535
*
36+
* <h2>{@code ExtensionContext} Scope</h2>
37+
*
38+
* <p>As of JUnit Jupiter 5.12, this API participates in the
39+
* {@link TestInstantiationAwareExtension} contract. Implementations of this API
40+
* may therefore choose to override
41+
* {@link TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
42+
* getTestInstantiationExtensionContextScope(ExtensionContext)} to require a
43+
* test-method scoped {@code ExtensionContext}. See
44+
* {@link #postProcessTestInstance(Object, ExtensionContext)} for further details.
45+
*
3646
* @since 5.0
3747
* @see #postProcessTestInstance(Object, ExtensionContext)
3848
* @see TestInstancePreDestroyCallback

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@
3838
* <p>Consult the documentation in {@link Extension} for details on constructor
3939
* requirements.
4040
*
41+
* <h2>{@code ExtensionContext} Scope</h2>
42+
*
43+
* <p>As of JUnit Jupiter 5.12, this API participates in the
44+
* {@link TestInstantiationAwareExtension} contract. Implementations of this API
45+
* may therefore choose to override
46+
* {@link TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
47+
* getTestInstantiationExtensionContextScope(ExtensionContext)} to require a
48+
* test-method scoped {@code ExtensionContext}. See
49+
* {@link #preConstructTestInstance(TestInstanceFactoryContext, ExtensionContext)}
50+
* for further details.
51+
*
4152
* @since 5.9
4253
* @see TestInstancePreDestroyCallback
4354
* @see TestInstanceFactory

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

Lines changed: 99 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,79 +14,119 @@
1414
import static org.apiguardian.api.API.Status.MAINTAINED;
1515

1616
import org.apiguardian.api.API;
17-
import org.junit.jupiter.api.TestInstance;
18-
import org.junit.jupiter.api.extension.ExtensionContext.Store;
1917

2018
/**
21-
* Interface for {@link Extension Extensions} that are aware and can influence
22-
* the instantiation of test instances.
19+
* {@code TestInstantiationAwareExtension} defines the API for {@link Extension
20+
* Extensions} that are aware of or influence the instantiation of test classes.
2321
*
24-
* <p>This interface is not indented to be implemented directly. Instead, extend
25-
* one of its sub-interfaces.
22+
* <p>This interface is not intended to be implemented directly. Instead, extensions
23+
* should implement one of the sub-interfaces listed below.
24+
*
25+
* <ul>
26+
* <li>{@link InvocationInterceptor}</li>
27+
* <li>{@link ParameterResolver}</li>
28+
* <li>{@link TestInstancePreConstructCallback}</li>
29+
* <li>{@link TestInstancePostProcessor}</li>
30+
* <li>{@link TestInstanceFactory}</li>
31+
* </ul>
32+
*
33+
* <p>See {@link #getTestInstantiationExtensionContextScope(ExtensionContext)} for
34+
* further details.
2635
*
2736
* @since 5.12
28-
* @see InvocationInterceptor#interceptTestClassConstructor
29-
* @see ParameterResolver
30-
* @see TestInstancePreConstructCallback
31-
* @see TestInstancePostProcessor
32-
* @see TestInstanceFactory
3337
*/
3438
@API(status = MAINTAINED, since = "5.13.3")
3539
public interface TestInstantiationAwareExtension extends Extension {
3640

3741
/**
38-
* Whether this extension should receive a test-scoped
39-
* {@link ExtensionContext} during the instantiation of test instances.
42+
* Determine whether this extension should receive a test-method scoped
43+
* {@link ExtensionContext} during the instantiation of test classes or
44+
* processing of test instances.
4045
*
41-
* <p>If an extension returns
42-
* {@link ExtensionContextScope#TEST_METHOD TEST_METHOD} from this method,
43-
* the following extension methods will be called with a test-scoped
44-
* {@link ExtensionContext} instead of a class-scoped one, unless the
45-
* {@link TestInstance.Lifecycle#PER_CLASS PER_CLASS} lifecycle is used:
46+
* <p>If an extension returns {@link ExtensionContextScope#TEST_METHOD TEST_METHOD}
47+
* from this method, methods defined in the following extension APIs will be
48+
* called with a test-method scoped {@code ExtensionContext} instead of a
49+
* test-class scoped context. Note, however, that a test-class scoped context
50+
* will always be supplied if the
51+
* {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS}
52+
* test instance lifecycle is used.
4653
*
4754
* <ul>
48-
* <li>{@link InvocationInterceptor#interceptTestClassConstructor}</li>
49-
* <li>{@link ParameterResolver} when resolving constructor parameters</li>
55+
* <li>{@link InvocationInterceptor}: only the
56+
* {@link InvocationInterceptor#interceptTestClassConstructor
57+
* interceptTestClassConstructor(...)} method</li>
58+
* <li>{@link ParameterResolver}: only when resolving constructor parameters</li>
5059
* <li>{@link TestInstancePreConstructCallback}</li>
5160
* <li>{@link TestInstancePostProcessor}</li>
5261
* <li>{@link TestInstanceFactory}</li>
5362
* </ul>
5463
*
55-
* <p>In such cases, implementations of these extension callbacks can
56-
* observe the following differences:
64+
* <p>When a test-method scoped {@code ExtensionContext} is supplied, implementations
65+
* of the above extension APIs will observe the following differences.
5766
*
5867
* <ul>
59-
* <li>{@link ExtensionContext#getElement() getElement()} may refer to the
60-
* test method and {@link ExtensionContext#getTestClass() getTestClass()}
61-
* may refer to a nested test class.
62-
* Use {@link TestInstanceFactoryContext#getTestClass()} to get the class
63-
* under construction.</li>
64-
* <li>{@link ExtensionContext#getTestMethod() getTestMethod()} is no longer
65-
* empty, unless the {@link TestInstance.Lifecycle#PER_CLASS PER_CLASS}
66-
* lifecycle is used.</li>
67-
* <li>If the callback adds a new {@link Store.CloseableResource} or
68-
* {@link AutoCloseable} to the {@link Store Store} (unless the
69-
* {@code junit.jupiter.extensions.store.close.autocloseable.enabled}
70-
* configuration parameter is set to {@code false}), then
71-
* the resource is closed just after the instance is destroyed.</li>
72-
* <li>The callbacks can now access data previously stored by
73-
* {@link TestTemplateInvocationContext}, unless the
74-
* {@link TestInstance.Lifecycle#PER_CLASS PER_CLASS} lifecycle is used.</li>
68+
* <li>
69+
* {@link ExtensionContext#getElement() getElement()} may refer to the
70+
* test method.
71+
* </li>
72+
* <li>
73+
* {@link ExtensionContext#getTestClass() getTestClass()} may refer to a
74+
* nested test class.
75+
* <ul>
76+
* <li>
77+
* For {@link TestInstancePostProcessor}, use {@code testInstance.getClass()}
78+
* to get the test class associated with the supplied instance.
79+
* </li>
80+
* <li>
81+
* For {@link TestInstanceFactory} and {@link TestInstancePreConstructCallback},
82+
* use {@link TestInstanceFactoryContext#getTestClass()} to get the
83+
* class under construction.
84+
* </li>
85+
* <li>
86+
* For {@link ParameterResolver}, when resolving a parameter for a
87+
* constructor, ensure that the
88+
* {@link ParameterContext#getDeclaringExecutable() Executable} is a
89+
* {@link java.lang.reflect.Constructor Constructor}, and then use
90+
* {@code constructor.getDeclaringClass()} to get the test class
91+
* associated with the constructor.
92+
* </li>
93+
* </ul>
94+
* </li>
95+
* <li>
96+
* {@link ExtensionContext#getTestMethod() getTestMethod()} is no longer
97+
* empty, unless the
98+
* {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS}
99+
* test instance lifecycle is used.
100+
* </li>
101+
* <li>
102+
* If the extension adds a {@link ExtensionContext.Store.CloseableResource
103+
* CloseableResource} or {@link AutoCloseable} to the
104+
* {@link ExtensionContext.Store Store} (unless the
105+
* {@code junit.jupiter.extensions.store.close.autocloseable.enabled}
106+
* configuration parameter is set to {@code false}), then the resource will
107+
* be closed just after the instance is destroyed.
108+
* </li>
109+
* <li>
110+
* Extensions can now access data previously stored by a
111+
* {@link TestTemplateInvocationContext}, unless the
112+
* {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS}
113+
* test instance lifecycle is used.
114+
* </li>
75115
* </ul>
76116
*
77117
* <p><strong>Note</strong>: The behavior which is enabled by returning
78118
* {@link ExtensionContextScope#TEST_METHOD TEST_METHOD} from this method
79119
* will become the default in future versions of JUnit. To ensure forward
80-
* compatibility, extension implementors are therefore advised to opt in,
81-
* even if they don't require the new functionality.
120+
* compatibility, extension authors are therefore advised to opt into this
121+
* feature, even if they do not require the new functionality.
82122
*
83-
* @implNote There are no guarantees about how often this method is called.
84-
* Therefore, implementations should be idempotent and avoid side
85-
* effects. They may, however, cache the result for performance in
86-
* the {@link Store Store} of the supplied
87-
* {@link ExtensionContext}, if necessary.
123+
* @implNote There are no guarantees about how often this method will be called.
124+
* Therefore, implementations should be idempotent and avoid side effects.
125+
* If computation of the return value is costly, implementations may wish to
126+
* cache the result in the {@link ExtensionContext.Store Store} of the supplied
127+
* {@code ExtensionContext}.
88128
* @param rootContext the root extension context to allow inspection of
89-
* configuration parameters; never {@code null}
129+
* configuration parameters; never {@code null}
90130
* @since 5.12
91131
*/
92132
@API(status = MAINTAINED, since = "5.13.3")
@@ -96,25 +136,25 @@ default ExtensionContextScope getTestInstantiationExtensionContextScope(Extensio
96136

97137
/**
98138
* {@code ExtensionContextScope} is used to define the scope of the
99-
* {@link ExtensionContext} passed to an extension during the instantiation
100-
* of test instances.
139+
* {@link ExtensionContext} supplied to an extension during the instantiation
140+
* of test classes or processing of test instances.
101141
*
102142
* @since 5.12
103-
* @see TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope
143+
* @see TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope(ExtensionContext)
104144
*/
105145
@API(status = MAINTAINED, since = "5.13.3")
106146
enum ExtensionContextScope {
107147

108148
/**
109-
* The extension should receive an {@link ExtensionContext} scoped to
110-
* in the <em>default</em> scope.
149+
* The extension should receive an {@link ExtensionContext} for the
150+
* the <em>default</em> scope.
111151
*
112152
* <p>The default scope is determined by the configuration parameter
113153
* {@link #DEFAULT_SCOPE_PROPERTY_NAME}. If not specified, extensions
114154
* will receive an {@link ExtensionContext} scoped to the test class.
115155
*
116156
* @deprecated This behavior will be removed from future versions of
117-
* JUnit and {@link #TEST_METHOD} will become the default.
157+
* JUnit, and {@link #TEST_METHOD} will become the default.
118158
*
119159
* @see #DEFAULT_SCOPE_PROPERTY_NAME
120160
*/
@@ -124,8 +164,12 @@ enum ExtensionContextScope {
124164

125165
/**
126166
* The extension should receive an {@link ExtensionContext} scoped to
127-
* the test method, unless the
128-
* {@link TestInstance.Lifecycle#PER_CLASS PER_CLASS} lifecycle is used.
167+
* the test method.
168+
*
169+
* <p>Note, however, that a test-class scoped context will always be
170+
* supplied if the
171+
* {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS}
172+
* test instance lifecycle is used.
129173
*/
130174
TEST_METHOD;
131175

@@ -140,6 +184,7 @@ enum ExtensionContextScope {
140184
* @see #DEFAULT
141185
*/
142186
public static final String DEFAULT_SCOPE_PROPERTY_NAME = "junit.jupiter.extensions.testinstantiation.extensioncontextscope.default";
187+
143188
}
144189

145190
}

0 commit comments

Comments
 (0)