-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TestInstanceFactory on enclosing class is not called for @Nested test class #1567
Comments
Just a comment: Since callbacks of the Extension (i.e. BeforeEachCallback, AfterEachCallback) normally also work for methods in nested Innerclasses, imO it should not be necessary to annotate those inner classes to make the TestInstanceFactory work. |
Thanks for raising the issue, @seanf. This sounds like it in fact might be a bug. So we'll look into it ASAP. |
in progress |
It's very likely specific to Lines 233 to 261 in 740af36
|
This change might brake existing code based on a release candidate. Perhaps it is worth, to mention that anywhere. |
I'm not concerned so much about a breaking change in a release candidate. The most important thing is that this has been brought to our attention before the GA release. In any case, it is in fact a bug, since the current behavior contradicts the documentation in the User Guide. The User Guide specifically states the following:
|
You're right: that's part of the same bug in the code. I'm adding a test for that particular use case as well. |
FYI: I improved the logging the example extension. public class CustomTestInstanceFactory implements TestInstanceFactory {
@Override
public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) {
try {
Optional<Object> outerInstance = factoryContext.getOuterInstance();
Class<?> testClass = factoryContext.getTestClass();
if (outerInstance.isPresent()) {
System.out.println("createTestInstance() called for inner class: " + testClass.getSimpleName());
return newInstance(testClass, outerInstance.get());
}
else {
System.out.println("createTestInstance() called for outer class: " + testClass.getSimpleName());
return newInstance(testClass);
}
}
catch (Exception e) {
throw new TestInstantiationException(e.getMessage(), e);
}
}
} |
And I simplified the example test class: // NB if this is enabled, the TestInstanceFactory is never called for inner class instances
@ExtendWith(CustomTestInstanceFactory.class)
// @TestInstance(TestInstance.Lifecycle.PER_CLASS)
// @TestInstance(TestInstance.Lifecycle.PER_METHOD)
class Outer {
@Test
void outer() {
}
@Nested
// @ExtendWith(CustomTestInstanceFactory.class)
class Inner {
@Test
void inner() {
}
@Nested
// @ExtendWith(CustomTestInstanceFactory.class)
class InnerInner {
@Test
void innerInner() {
}
}
}
} |
With my current changes on my machine, that now outputs the following
|
And uncommenting the duplicated registrations for the custom factory on the |
This issue has been addressed in 87bda94; however, I am reopening this issue in order to ensure that the documentation is consistent. |
Team Decision: Align the behavior between conventional class hierarchies and nested class structures with regard to disallowing multiple registrations of |
I am closing this issue now, since the aforementioned team decision will now be addressed in #1573. |
Overview
If I use nested classes together with a
TestIntanceFactory
on the outer class, the instance factory is not called for the inner class, unless a different factory class is used.I would expect that I can use the same factory on the outer class and the inner class, and have it called both for outer and inner instances. Ideally the factory on the outer class would be "inherited" by the inner class automatically. (It's not clear from the docs if extensions are meant to be propagated to nested classes the way other things are.)
Note that the existing unit test
org.junit.jupiter.engine.extension.TestInstanceFactoryTests#instanceFactoriesInNestedClassHierarchy
(org.junit.jupiter.engine.extension.TestInstanceFactoryTests.OuterTestCase
) uses a different factory class for the outer class and the inner class.JUnit version: 5.3.0-RC1
Example Test
The logging shows that
createTestInstance()
is never called for inner class instances, unless you comment out@ExtendWith(JUnit5ExtensionJava.class)
on the outer class.Note that if I simply clone the extension class and use one factory class for the outer class and the other factory class for the inner class, both factories are called as expected. It's only when the same extension is specified on both classes, or perhaps "inherited" from the outer to the inner class, that the inner instances are skipped.
I haven't checked whether this applies to other extension types or just
TestInstanceFactory
.The text was updated successfully, but these errors were encountered: