Skip to content

Commit ab7b5e5

Browse files
committed
Demo how to use SpringClassRule in nested test classes
Due to restrictions imposed by JUnit 4, the SpringClassRule must be declared as a public static field, which makes it impossible to be declared directly within a nested (i.e., inner) test class. This commit demonstrates a work-around that makes it possible to use the SpringClassRule and SpringMethodRule in a nested (i.e., inner) test class when using a custom JUnit 4 runner such as the HierarchicalContextRunner from Stefan Bechtold. The trick is to have inner test classes extend a class that properly declares the SpringClassRule and SpringMethodRule. The SpringRuleConfigurer in this commit serves as an example. Note, however, that each such nested test class must declare its own @ContextConfiguration. Furthermore, TestExecutionListeners in the Spring TestContext Framework are not applied to the enclosing instance of such an inner test class, meaning that @Autowired fields in the enclosing instance will not be injected, etc. Issue: SPR-14150
1 parent 09f1674 commit ab7b5e5

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,8 @@ project("spring-test") {
10221022
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
10231023
testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
10241024
testCompile("javax.cache:cache-api:1.0.0")
1025+
testCompile('de.bechte.junit:junit-hierarchicalcontextrunner:4.12.1')
1026+
10251027
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
10261028
testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}") // Java Util Logging for JUnit 5
10271029
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2002-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.junit4.nested;
18+
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.test.context.ContextConfiguration;
26+
import org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests.TopLevelConfig;
27+
import org.springframework.test.context.junit4.rules.SpringClassRule;
28+
import org.springframework.test.context.junit4.rules.SpringMethodRule;
29+
30+
import static org.junit.Assert.assertEquals;
31+
import static org.junit.Assert.assertNull;
32+
33+
import de.bechte.junit.runners.context.HierarchicalContextRunner;
34+
35+
/**
36+
* JUnit 4 based integration tests for <em>nested</em> test classes that are
37+
* executed via a custom JUnit 4 {@link HierarchicalContextRunner} and Spring's
38+
* {@link SpringClassRule} and {@link SpringMethodRule} support.
39+
*
40+
* @author Sam Brannen
41+
* @since 5.0
42+
*/
43+
@RunWith(HierarchicalContextRunner.class)
44+
@ContextConfiguration(classes = TopLevelConfig.class)
45+
public class NestedTestsWithSpringRulesTests extends SpringRuleConfigurer {
46+
47+
@Autowired
48+
String foo;
49+
50+
51+
@Test
52+
public void topLevelTest() {
53+
assertEquals("foo", foo);
54+
}
55+
56+
57+
@ContextConfiguration(classes = NestedConfig.class)
58+
public class NestedTestCase extends SpringRuleConfigurer {
59+
60+
@Autowired
61+
String bar;
62+
63+
64+
@Test
65+
public void nestedTest() throws Exception {
66+
// Note: the following would fail since TestExecutionListeners in
67+
// the Spring TestContext Framework are not applied to the enclosing
68+
// instance of an inner test class.
69+
//
70+
// assertEquals("foo", foo);
71+
72+
assertNull("@Autowired field in enclosing instance should be null.", foo);
73+
assertEquals("bar", bar);
74+
}
75+
}
76+
77+
// -------------------------------------------------------------------------
78+
79+
@Configuration
80+
public static class TopLevelConfig {
81+
82+
@Bean
83+
String foo() {
84+
return "foo";
85+
}
86+
}
87+
88+
@Configuration
89+
public static class NestedConfig {
90+
91+
@Bean
92+
String bar() {
93+
return "bar";
94+
}
95+
}
96+
97+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2002-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.junit4.nested;
18+
19+
import org.junit.ClassRule;
20+
import org.junit.Rule;
21+
22+
import org.springframework.test.context.junit4.rules.SpringClassRule;
23+
import org.springframework.test.context.junit4.rules.SpringMethodRule;
24+
25+
/**
26+
* Abstract base test class that preconfigures the {@link SpringClassRule} and
27+
* {@link SpringMethodRule}.
28+
*
29+
* @author Sam Brannen
30+
* @since 5.0
31+
*/
32+
public abstract class SpringRuleConfigurer {
33+
34+
@ClassRule
35+
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
36+
37+
@Rule
38+
public final SpringMethodRule springMethodRule = new SpringMethodRule();
39+
40+
}

0 commit comments

Comments
 (0)