Skip to content

Support nested test classes with SpringClassRule & SpringMethodRule [SPR-14150] #18722

Closed
@spring-projects-issues

Description

@spring-projects-issues

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

  1. 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.
  2. Ensure that JUnit Jupiter based @Nested test classes work with the TestContext framework.
  3. Ensure that SpringClassRule and SpringMethodRule 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:

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:

Referenced from: commits ab7b5e5, e574820

Metadata

Metadata

Assignees

Labels

in: testIssues in the test modulestatus: declinedA suggestion or change that we don't feel we should currently applytype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions