Skip to content

Commit 21a5ab7

Browse files
committed
Log a warning during tests when multiple JSONOjects on the class path
Closes gh-9248
1 parent cbdab9e commit 21a5ab7

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed

spring-boot-test/pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@
117117
<artifactId>spring-boot-test-support</artifactId>
118118
<scope>test</scope>
119119
</dependency>
120+
<dependency>
121+
<groupId>ch.qos.logback</groupId>
122+
<artifactId>logback-classic</artifactId>
123+
<scope>test</scope>
124+
</dependency>
120125
<dependency>
121126
<groupId>org.apache.tomcat.embed</groupId>
122127
<artifactId>tomcat-embed-core</artifactId>
@@ -138,6 +143,16 @@
138143
<artifactId>kotlin-runtime</artifactId>
139144
<scope>test</scope>
140145
</dependency>
146+
<dependency>
147+
<groupId>org.slf4j</groupId>
148+
<artifactId>jcl-over-slf4j</artifactId>
149+
<scope>test</scope>
150+
</dependency>
151+
<dependency>
152+
<groupId>org.slf4j</groupId>
153+
<artifactId>slf4j-api</artifactId>
154+
<scope>test</scope>
155+
</dependency>
141156
<dependency>
142157
<groupId>org.spockframework</groupId>
143158
<artifactId>spock-core</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2012-2017 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.boot.test.json;
18+
19+
import java.net.URL;
20+
import java.util.ArrayList;
21+
import java.util.Enumeration;
22+
import java.util.List;
23+
24+
import org.apache.commons.logging.Log;
25+
import org.apache.commons.logging.LogFactory;
26+
27+
import org.springframework.context.ConfigurableApplicationContext;
28+
import org.springframework.test.context.ContextConfigurationAttributes;
29+
import org.springframework.test.context.ContextCustomizer;
30+
import org.springframework.test.context.ContextCustomizerFactory;
31+
import org.springframework.test.context.MergedContextConfiguration;
32+
33+
/**
34+
* A {@link ContextCustomizerFactory} that produces a {@link ContextCustomizer} that warns
35+
* the user when multiple occurrences of {@code JSONObject} are found on the class path.
36+
*
37+
* @author Andy Wilkinson
38+
*/
39+
class DuplicateJsonObjectContextCustomizerFactory implements ContextCustomizerFactory {
40+
41+
@Override
42+
public ContextCustomizer createContextCustomizer(Class<?> testClass,
43+
List<ContextConfigurationAttributes> configAttributes) {
44+
return new DuplicateJsonObjectContextCustomizer();
45+
}
46+
47+
private static class DuplicateJsonObjectContextCustomizer
48+
implements ContextCustomizer {
49+
50+
private final Log logger = LogFactory
51+
.getLog(DuplicateJsonObjectContextCustomizer.class);
52+
53+
@Override
54+
public void customizeContext(ConfigurableApplicationContext context,
55+
MergedContextConfiguration mergedConfig) {
56+
List<URL> jsonObjects = findJsonObjects();
57+
if (jsonObjects.size() > 1) {
58+
logDuplicateJsonObjectsWarning(jsonObjects);
59+
}
60+
}
61+
62+
private List<URL> findJsonObjects() {
63+
List<URL> jsonObjects = new ArrayList<URL>();
64+
try {
65+
Enumeration<URL> resources = getClass().getClassLoader()
66+
.getResources("org/json/JSONObject.class");
67+
while (resources.hasMoreElements()) {
68+
jsonObjects.add(resources.nextElement());
69+
}
70+
}
71+
catch (Exception ex) {
72+
// Continue
73+
}
74+
return jsonObjects;
75+
}
76+
77+
private void logDuplicateJsonObjectsWarning(List<URL> jsonObjects) {
78+
StringBuilder message = new StringBuilder("\n\nFound multiple occurrences of"
79+
+ " org.json.JSONObject on the class path:\n\n");
80+
for (URL jsonObject : jsonObjects) {
81+
message.append("\t" + jsonObject + "\n");
82+
}
83+
message.append("\nYou may wish to exclude one of them to ensure"
84+
+ " predictable runtime behaviour\n");
85+
this.logger.warn(message);
86+
}
87+
88+
}
89+
90+
}

spring-boot-test/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ org.springframework.test.context.ContextCustomizerFactory=\
33
org.springframework.boot.test.context.ImportsContextCustomizerFactory,\
44
org.springframework.boot.test.context.SpringBootTestContextCustomizerFactory,\
55
org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFactory,\
6+
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory,\
67
org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory
78

89
# Test Execution Listeners
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2012-2017 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.boot.test.json;
18+
19+
import org.junit.Rule;
20+
import org.junit.Test;
21+
import org.junit.runner.RunWith;
22+
23+
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
24+
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
25+
import org.springframework.boot.test.rule.OutputCapture;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
/**
30+
* Tests for {@link DuplicateJsonObjectContextCustomizerFactory}.
31+
*
32+
* @author Andy Wilkinson
33+
*/
34+
@RunWith(ModifiedClassPathRunner.class)
35+
@ClassPathOverrides("org.json:json:20140107")
36+
public class DuplicateJsonObjectContextCustomizerFactoryTests {
37+
38+
@Rule
39+
public OutputCapture output = new OutputCapture();
40+
41+
@Test
42+
public void warningForMultipleVersions() {
43+
new DuplicateJsonObjectContextCustomizerFactory()
44+
.createContextCustomizer(null, null).customizeContext(null, null);
45+
assertThat(this.output.toString()).contains(
46+
"Found multiple occurrences of org.json.JSONObject on the class path:");
47+
}
48+
49+
}

0 commit comments

Comments
 (0)