Description
Benoit AVERTY opened SPR-14150 and commented
Status Quo
The Spring TestContext Framework has traditionally supported only top-level or static nested test classes. With support for @Nested
test classes in JUnit 5 and custom runners in JUnit 4, however, there is increased need to support nested non-static test classes (i.e., inner classes).
Deliverables
- Introduce support for loading a test
ApplicationContext
via@ContextConfiguration
and related annotations for a nested test class.- This already works without modifications to the existing code base: a nested (i.e., non-static inner) test class is still a
Class
, so the TestContext framework doesn't need to do anything special here.
- This already works without modifications to the existing code base: a nested (i.e., non-static inner) test class is still a
- Ensure that JUnit Jupiter based
@Nested
test classes work with the TestContext framework.- This already works for the same reasons mentioned for deliverable Spring core JMS pom.xml #1.
- Ensure that
SpringClassRule
andSpringMethodRule
work in conjunction with JUnit 4 based runners that support nested test classes.- Introduced a workaround which is documented in this issue's comments section.
JUnit 4 Hierarchical Runners
When using the @Rule
and @ClassRule
classes SpringMethodRule
and SpringClassRule
in conjunction with a custom JUnit 4 Runner
that allows one to use nested classes to create hierarchical tests, the tests in subclasses fail with an IllegalStateException
.
Examples of hierarchical runners:
- https://github.com/bechte/junit-hierarchicalcontextrunner/wiki
- https://github.com/NitorCreations/CoreComponents/tree/master/junit-runners
The second one doesn't have the same error, but I'm guessing the problem is similar.
java.lang.IllegalStateException: Failed to find 'public static final SpringClassRule' field in test class [com.example.unit.testing.application.PlacingOrderTest$WithExistingCustomer]. Consult the javadoc for SpringClassRule for details.
at org.springframework.test.context.junit4.rules.SpringMethodRule.validateSpringClassRuleConfiguration(SpringMethodRule.java:233)
at org.springframework.test.context.junit4.rules.SpringMethodRule.apply(SpringMethodRule.java:143)
at de.bechte.junit.runners.context.statements.builder.HierarchicalRunRulesStatementBuilder.createStatement(HierarchicalRunRulesStatementBuilder.java:42)
at de.bechte.junit.runners.context.processing.MethodExecutor.run(MethodExecutor.java:80)
at de.bechte.junit.runners.context.processing.MethodExecutor.run(MethodExecutor.java:57)
at de.bechte.junit.runners.context.statements.RunChildren.evaluate(RunChildren.java:38)
at de.bechte.junit.runners.context.statements.RunAll.evaluate(RunAll.java:27)
at de.bechte.junit.runners.context.statements.StatementExecutor.execute(StatementExecutor.java:28)
at de.bechte.junit.runners.context.HierarchicalContextRunner.run(HierarchicalContextRunner.java:134)
at de.bechte.junit.runners.context.processing.ContextExecutor.run(ContextExecutor.java:26)
at de.bechte.junit.runners.context.processing.ContextExecutor.run(ContextExecutor.java:15)
at de.bechte.junit.runners.context.statements.RunChildren.evaluate(RunChildren.java:38)
at de.bechte.junit.runners.context.statements.RunAll.evaluate(RunAll.java:27)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.springframework.test.context.junit4.statements.ProfileValueChecker.evaluate(ProfileValueChecker.java:103)
at org.springframework.test.context.junit4.rules.SpringClassRule$TestContextManagerCacheEvictor.evaluate(SpringClassRule.java:248)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at de.bechte.junit.runners.context.statements.StatementExecutor.execute(StatementExecutor.java:28)
at de.bechte.junit.runners.context.HierarchicalContextRunner.run(HierarchicalContextRunner.java:134)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
The exception makes sense because the nested class indeed doesn't have the static SpringClassRule
. But it can't have it because the nested class isn't static. Moreover, I'm not sure it would need it because the rule would be evaluated twice.
Affects: 4.2.5
Issue Links:
- Discover test configuration on enclosing class for nested test class [SPR-15366] #19930 Discover test configuration on enclosing class for nested test class