Log a warning during tests when multiple JSONOjects on the class path

Closes gh-9248
This commit is contained in:
Andy Wilkinson 2017-06-06 21:35:33 +01:00
parent cbdab9edb3
commit 21a5ab7875
4 changed files with 155 additions and 0 deletions

View File

@ -117,6 +117,11 @@
<artifactId>spring-boot-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
@ -138,6 +143,16 @@
<artifactId>kotlin-runtime</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>

View File

@ -0,0 +1,90 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.test.json;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;
/**
* A {@link ContextCustomizerFactory} that produces a {@link ContextCustomizer} that warns
* the user when multiple occurrences of {@code JSONObject} are found on the class path.
*
* @author Andy Wilkinson
*/
class DuplicateJsonObjectContextCustomizerFactory implements ContextCustomizerFactory {
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
return new DuplicateJsonObjectContextCustomizer();
}
private static class DuplicateJsonObjectContextCustomizer
implements ContextCustomizer {
private final Log logger = LogFactory
.getLog(DuplicateJsonObjectContextCustomizer.class);
@Override
public void customizeContext(ConfigurableApplicationContext context,
MergedContextConfiguration mergedConfig) {
List<URL> jsonObjects = findJsonObjects();
if (jsonObjects.size() > 1) {
logDuplicateJsonObjectsWarning(jsonObjects);
}
}
private List<URL> findJsonObjects() {
List<URL> jsonObjects = new ArrayList<URL>();
try {
Enumeration<URL> resources = getClass().getClassLoader()
.getResources("org/json/JSONObject.class");
while (resources.hasMoreElements()) {
jsonObjects.add(resources.nextElement());
}
}
catch (Exception ex) {
// Continue
}
return jsonObjects;
}
private void logDuplicateJsonObjectsWarning(List<URL> jsonObjects) {
StringBuilder message = new StringBuilder("\n\nFound multiple occurrences of"
+ " org.json.JSONObject on the class path:\n\n");
for (URL jsonObject : jsonObjects) {
message.append("\t" + jsonObject + "\n");
}
message.append("\nYou may wish to exclude one of them to ensure"
+ " predictable runtime behaviour\n");
this.logger.warn(message);
}
}
}

View File

@ -3,6 +3,7 @@ org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.boot.test.context.ImportsContextCustomizerFactory,\
org.springframework.boot.test.context.SpringBootTestContextCustomizerFactory,\
org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFactory,\
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory,\
org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory
# Test Execution Listeners

View File

@ -0,0 +1,49 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.test.json;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
import org.springframework.boot.test.rule.OutputCapture;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DuplicateJsonObjectContextCustomizerFactory}.
*
* @author Andy Wilkinson
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathOverrides("org.json:json:20140107")
public class DuplicateJsonObjectContextCustomizerFactoryTests {
@Rule
public OutputCapture output = new OutputCapture();
@Test
public void warningForMultipleVersions() {
new DuplicateJsonObjectContextCustomizerFactory()
.createContextCustomizer(null, null).customizeContext(null, null);
assertThat(this.output.toString()).contains(
"Found multiple occurrences of org.json.JSONObject on the class path:");
}
}