Overview
A comment in SPR-15366 has made me aware of a potential bug in JUnit Jupiter's handling of @BeforeEach methods with regard to the ExtensionContext supplied to a ParameterResolver registered for an enclosing test class when executing a test method within a @Nested test class.
Specifically, Jupiter invokes a @BeforeEach method in the enclosing class using the ExtensionContext for a @Test method in a @Nested class. The same may be true for other lifecycle callback methods as well, but I have not investigated that.
Analysis
It would appear that the cause of this behavior is due to a combination of how ClassTestDescriptor.invokeMethodInExtensionContext(Method, ExtensionContext, ExtensionRegistry) and TestMethodTestDescriptor.invokeBeforeEachMethods(JupiterEngineExecutionContext) operate. The latter invokes each synthesized BeforeEachMethodAdapter using the ExtensionContext for the current test method instead of supplying the ExtensionContext for the context in which the method is declared. Consequently, if a ParameterResolver is asked to resolve a parameter for a @BeforeEach method in an enclosing class and the resolver needs the test class (or information tied to the test class via annotations) to resolve the parameter, then the resolver gets the test class for the currently executing @Nested test class when invoking extensionContext.getRequiredTestClass().
However, this behavior does not appear to apply to the invocation of TestInstancePostProcessor implementations as can be seen in TestInstancePostProcessorTests.
Similarly, the behavior is different for a ParameterResolver applied to the constructor of an enclosing class for the currently executing @Nested test class.
Related Issues
Deliverables
Overview
A comment in SPR-15366 has made me aware of a potential bug in JUnit Jupiter's handling of
@BeforeEachmethods with regard to theExtensionContextsupplied to aParameterResolverregistered for an enclosing test class when executing a test method within a@Nestedtest class.Specifically, Jupiter invokes a
@BeforeEachmethod in the enclosing class using theExtensionContextfor a@Testmethod in a@Nestedclass. The same may be true for other lifecycle callback methods as well, but I have not investigated that.Analysis
It would appear that the cause of this behavior is due to a combination of how
ClassTestDescriptor.invokeMethodInExtensionContext(Method, ExtensionContext, ExtensionRegistry)andTestMethodTestDescriptor.invokeBeforeEachMethods(JupiterEngineExecutionContext)operate. The latter invokes each synthesizedBeforeEachMethodAdapterusing theExtensionContextfor the current test method instead of supplying theExtensionContextfor the context in which the method is declared. Consequently, if aParameterResolveris asked to resolve a parameter for a@BeforeEachmethod in an enclosing class and the resolver needs the test class (or information tied to the test class via annotations) to resolve the parameter, then the resolver gets the test class for the currently executing@Nestedtest class when invokingextensionContext.getRequiredTestClass().However, this behavior does not appear to apply to the invocation of
TestInstancePostProcessorimplementations as can be seen inTestInstancePostProcessorTests.Similarly, the behavior is different for a
ParameterResolverapplied to the constructor of an enclosing class for the currently executing@Nestedtest class.Related Issues
Deliverables
@BeforeAll@AfterAll@BeforeEach@AfterEachExtensionContext.