Commit dd0ce544 authored by Andy Wilkinson's avatar Andy Wilkinson Committed by Stephane Nicoll

Improve the type-safety of ContextLoader for servlet and reactive web

parent 19ddfad6
...@@ -58,6 +58,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; ...@@ -58,6 +58,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.ContextConsumer; import org.springframework.boot.test.context.ContextConsumer;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.core.CassandraOperations; import org.springframework.data.cassandra.core.CassandraOperations;
...@@ -79,8 +80,9 @@ import static org.mockito.Mockito.mock; ...@@ -79,8 +80,9 @@ import static org.mockito.Mockito.mock;
*/ */
public class HealthIndicatorAutoConfigurationTests { public class HealthIndicatorAutoConfigurationTests {
public final ContextLoader contextLoader = new ContextLoader().autoConfig( public final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
HealthIndicatorAutoConfiguration.class, ManagementServerProperties.class); .standard().autoConfig(HealthIndicatorAutoConfiguration.class,
ManagementServerProperties.class);
@Test @Test
public void defaultHealthIndicator() { public void defaultHealthIndicator() {
...@@ -378,7 +380,7 @@ public class HealthIndicatorAutoConfigurationTests { ...@@ -378,7 +380,7 @@ public class HealthIndicatorAutoConfigurationTests {
.load(hasSingleHealthIndicator(ApplicationHealthIndicator.class)); .load(hasSingleHealthIndicator(ApplicationHealthIndicator.class));
} }
private ContextConsumer hasSingleHealthIndicator( private ContextConsumer<AnnotationConfigApplicationContext> hasSingleHealthIndicator(
Class<? extends HealthIndicator> type) { Class<? extends HealthIndicator> type) {
return context -> { return context -> {
Map<String, HealthIndicator> beans = context Map<String, HealthIndicator> beans = context
......
...@@ -29,6 +29,7 @@ import org.junit.Test; ...@@ -29,6 +29,7 @@ import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -59,29 +60,36 @@ public class HazelcastAutoConfigurationClientTests { ...@@ -59,29 +60,36 @@ public class HazelcastAutoConfigurationClientTests {
} }
} }
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.autoConfig(HazelcastAutoConfiguration.class); .standard().autoConfig(HazelcastAutoConfiguration.class);
@Test @Test
public void systemProperty() throws IOException { public void systemProperty() throws IOException {
this.contextLoader.systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY, this.contextLoader
"classpath:org/springframework/boot/autoconfigure/hazelcast/" .systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY,
+ "hazelcast-client-specific.xml").load(context -> { "classpath:org/springframework/boot/autoconfigure/hazelcast/"
HazelcastInstance hazelcastInstance = context + "hazelcast-client-specific.xml")
.getBean(HazelcastInstance.class); .load(context -> {
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); HazelcastInstance hazelcastInstance = context
assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); .getBean(HazelcastInstance.class);
}); assertThat(hazelcastInstance)
.isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
});
} }
@Test @Test
public void explicitConfigFile() throws IOException { public void explicitConfigFile() throws IOException {
this.contextLoader.env("spring.hazelcast.config=org/springframework/boot/autoconfigure/" this.contextLoader
+ "hazelcast/hazelcast-client-specific.xml").load(context -> { .env("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); + "hazelcast/hazelcast-client-specific.xml")
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); .load(context -> {
assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); HazelcastInstance hazelcastInstance = context
}); .getBean(HazelcastInstance.class);
assertThat(hazelcastInstance)
.isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
});
} }
@Test @Test
...@@ -90,26 +98,28 @@ public class HazelcastAutoConfigurationClientTests { ...@@ -90,26 +98,28 @@ public class HazelcastAutoConfigurationClientTests {
.load(context -> { .load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class); .getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); assertThat(hazelcastInstance)
.isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
}); });
} }
@Test @Test
public void unknownConfigFile() { public void unknownConfigFile() {
this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml") this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml").loadAndFail(
.loadAndFail(BeanCreationException.class, ex -> BeanCreationException.class,
assertThat(ex.getMessage()).contains("foo/bar/unknown.xml")); ex -> assertThat(ex.getMessage()).contains("foo/bar/unknown.xml"));
} }
@Test @Test
public void clientConfigTakesPrecedence() { public void clientConfigTakesPrecedence() {
this.contextLoader.config(HazelcastServerAndClientConfig.class) this.contextLoader.config(HazelcastServerAndClientConfig.class)
.env("spring.hazelcast.config=this-is-ignored.xml").load(context -> { .env("spring.hazelcast.config=this-is-ignored.xml").load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class); .getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); assertThat(hazelcastInstance)
}); .isInstanceOf(HazelcastClientProxy.class);
});
} }
@Configuration @Configuration
......
...@@ -30,6 +30,7 @@ import org.springframework.beans.factory.BeanCreationException; ...@@ -30,6 +30,7 @@ import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
...@@ -45,8 +46,8 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -45,8 +46,8 @@ import static org.assertj.core.api.Assertions.assertThat;
@ClassPathExclusions("hazelcast-client-*.jar") @ClassPathExclusions("hazelcast-client-*.jar")
public class HazelcastAutoConfigurationServerTests { public class HazelcastAutoConfigurationServerTests {
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.autoConfig(HazelcastAutoConfiguration.class); .standard().autoConfig(HazelcastAutoConfiguration.class);
@Test @Test
public void defaultConfigFile() throws IOException { public void defaultConfigFile() throws IOException {
...@@ -61,8 +62,9 @@ public class HazelcastAutoConfigurationServerTests { ...@@ -61,8 +62,9 @@ public class HazelcastAutoConfigurationServerTests {
@Test @Test
public void systemProperty() throws IOException { public void systemProperty() throws IOException {
this.contextLoader.systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY, this.contextLoader
"classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml") .systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY,
"classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml")
.load(context -> { .load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
...@@ -75,32 +77,36 @@ public class HazelcastAutoConfigurationServerTests { ...@@ -75,32 +77,36 @@ public class HazelcastAutoConfigurationServerTests {
@Test @Test
public void explicitConfigFile() throws IOException { public void explicitConfigFile() throws IOException {
this.contextLoader.env("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" this.contextLoader
+ "hazelcast-specific.xml").load(context -> { .env("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/"
HazelcastInstance hazelcastInstance = context + "hazelcast-specific.xml")
.getBean(HazelcastInstance.class); .load(context -> {
assertThat(hazelcastInstance.getConfig().getConfigurationFile()).isEqualTo( HazelcastInstance hazelcastInstance = context
new ClassPathResource("org/springframework/boot/autoconfigure/hazelcast" .getBean(HazelcastInstance.class);
+ "/hazelcast-specific.xml").getFile()); assertThat(hazelcastInstance.getConfig().getConfigurationFile())
}); .isEqualTo(new ClassPathResource(
"org/springframework/boot/autoconfigure/hazelcast"
+ "/hazelcast-specific.xml").getFile());
});
} }
@Test @Test
public void explicitConfigUrl() throws IOException { public void explicitConfigUrl() throws IOException {
this.contextLoader this.contextLoader.env("spring.hazelcast.config=hazelcast-default.xml")
.env("spring.hazelcast.config=hazelcast-default.xml").load(context -> { .load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class); .getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast-default.xml").getURL()); .isEqualTo(new ClassPathResource("hazelcast-default.xml")
}); .getURL());
});
} }
@Test @Test
public void unknownConfigFile() { public void unknownConfigFile() {
this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml") this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml").loadAndFail(
.loadAndFail(BeanCreationException.class, ex -> BeanCreationException.class,
assertThat(ex.getMessage()).contains("foo/bar/unknown.xml")); ex -> assertThat(ex.getMessage()).contains("foo/bar/unknown.xml"));
} }
@Test @Test
...@@ -109,15 +115,16 @@ public class HazelcastAutoConfigurationServerTests { ...@@ -109,15 +115,16 @@ public class HazelcastAutoConfigurationServerTests {
HazelcastInstance existingHazelcastInstance = Hazelcast HazelcastInstance existingHazelcastInstance = Hazelcast
.newHazelcastInstance(config); .newHazelcastInstance(config);
try { try {
this.contextLoader.config(HazelcastConfigWithName.class).env( this.contextLoader.config(HazelcastConfigWithName.class)
"spring.hazelcast.config=this-is-ignored.xml").load(context -> { .env("spring.hazelcast.config=this-is-ignored.xml").load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class); .getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getInstanceName()) assertThat(hazelcastInstance.getConfig().getInstanceName())
.isEqualTo("my-test-instance"); .isEqualTo("my-test-instance");
// Should reuse any existing instance by default. // Should reuse any existing instance by default.
assertThat(hazelcastInstance).isEqualTo(existingHazelcastInstance); assertThat(hazelcastInstance)
}); .isEqualTo(existingHazelcastInstance);
});
} }
finally { finally {
existingHazelcastInstance.shutdown(); existingHazelcastInstance.shutdown();
...@@ -128,12 +135,12 @@ public class HazelcastAutoConfigurationServerTests { ...@@ -128,12 +135,12 @@ public class HazelcastAutoConfigurationServerTests {
public void configInstanceWithoutName() { public void configInstanceWithoutName() {
this.contextLoader.config(HazelcastConfigNoName.class) this.contextLoader.config(HazelcastConfigNoName.class)
.env("spring.hazelcast.config=this-is-ignored.xml").load(context -> { .env("spring.hazelcast.config=this-is-ignored.xml").load(context -> {
HazelcastInstance hazelcastInstance = context HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class); .getBean(HazelcastInstance.class);
Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig() Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig()
.getQueueConfigs(); .getQueueConfigs();
assertThat(queueConfigs).hasSize(1).containsKey("another-queue"); assertThat(queueConfigs).hasSize(1).containsKey("another-queue");
}); });
} }
@Configuration @Configuration
......
...@@ -22,6 +22,7 @@ import com.hazelcast.core.HazelcastInstance; ...@@ -22,6 +22,7 @@ import com.hazelcast.core.HazelcastInstance;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -33,14 +34,15 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -33,14 +34,15 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class HazelcastAutoConfigurationTests { public class HazelcastAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.autoConfig(HazelcastAutoConfiguration.class); .standard().autoConfig(HazelcastAutoConfiguration.class);
@Test @Test
public void defaultConfigFile() throws IOException { public void defaultConfigFile() throws IOException {
// no hazelcast-client.xml and hazelcast.xml is present in root classpath // no hazelcast-client.xml and hazelcast.xml is present in root classpath
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); HazelcastInstance hazelcastInstance = context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast.xml").getURL()); .isEqualTo(new ClassPathResource("hazelcast.xml").getURL());
}); });
......
...@@ -41,6 +41,7 @@ import org.springframework.boot.jdbc.DatabaseDriver; ...@@ -41,6 +41,7 @@ import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.test.context.ContextConsumer; import org.springframework.boot.test.context.ContextConsumer;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.boot.test.context.HidePackagesClassLoader; import org.springframework.boot.test.context.HidePackagesClassLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
...@@ -57,15 +58,16 @@ import static org.mockito.Mockito.mock; ...@@ -57,15 +58,16 @@ import static org.mockito.Mockito.mock;
*/ */
public class DataSourceAutoConfigurationTests { public class DataSourceAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.autoConfig(DataSourceAutoConfiguration.class) .standard().autoConfig(DataSourceAutoConfiguration.class)
.env("spring.datasource.initialize=false", .env("spring.datasource.initialize=false",
"spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()); "spring.datasource.url:jdbc:hsqldb:mem:testdb-"
+ new Random().nextInt());
@Test @Test
public void testDefaultDataSourceExists() throws Exception { public void testDefaultDataSourceExists() throws Exception {
this.contextLoader.load(context -> this.contextLoader.load(
assertThat(context.getBean(DataSource.class)).isNotNull()); context -> assertThat(context.getBean(DataSource.class)).isNotNull());
} }
@Test @Test
...@@ -93,25 +95,25 @@ public class DataSourceAutoConfigurationTests { ...@@ -93,25 +95,25 @@ public class DataSourceAutoConfigurationTests {
@Test @Test
public void testBadDriverClass() throws Exception { public void testBadDriverClass() throws Exception {
this.contextLoader.env("spring.datasource.driverClassName:org.none.jdbcDriver") this.contextLoader.env("spring.datasource.driverClassName:org.none.jdbcDriver")
.loadAndFail(BeanCreationException.class, ex -> .loadAndFail(BeanCreationException.class,
assertThat(ex.getMessage()).contains("org.none.jdbcDriver")); ex -> assertThat(ex.getMessage())
.contains("org.none.jdbcDriver"));
} }
@Test @Test
public void hikariValidatesConnectionByDefault() throws Exception { public void hikariValidatesConnectionByDefault() throws Exception {
assertDataSource(HikariDataSource.class, assertDataSource(HikariDataSource.class,
Collections.singletonList("org.apache.tomcat"), Collections.singletonList("org.apache.tomcat"), dataSource ->
dataSource -> // Use Connection#isValid()
// Use Connection#isValid() assertThat(dataSource.getConnectionTestQuery()).isNull());
assertThat(dataSource.getConnectionTestQuery()).isNull()
);
} }
@Test @Test
public void tomcatIsFallback() throws Exception { public void tomcatIsFallback() throws Exception {
assertDataSource(org.apache.tomcat.jdbc.pool.DataSource.class, assertDataSource(org.apache.tomcat.jdbc.pool.DataSource.class,
Collections.singletonList("com.zaxxer.hikari"), dataSource -> Collections.singletonList("com.zaxxer.hikari"),
assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb")); dataSource -> assertThat(dataSource.getUrl())
.startsWith("jdbc:hsqldb:mem:testdb"));
} }
@Test @Test
...@@ -127,8 +129,9 @@ public class DataSourceAutoConfigurationTests { ...@@ -127,8 +129,9 @@ public class DataSourceAutoConfigurationTests {
@Test @Test
public void commonsDbcp2IsFallback() throws Exception { public void commonsDbcp2IsFallback() throws Exception {
assertDataSource(BasicDataSource.class, assertDataSource(BasicDataSource.class,
Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), dataSource -> Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"),
assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb")); dataSource -> assertThat(dataSource.getUrl())
.startsWith("jdbc:hsqldb:mem:testdb"));
} }
@Test @Test
...@@ -136,7 +139,8 @@ public class DataSourceAutoConfigurationTests { ...@@ -136,7 +139,8 @@ public class DataSourceAutoConfigurationTests {
assertDataSource(org.apache.commons.dbcp2.BasicDataSource.class, assertDataSource(org.apache.commons.dbcp2.BasicDataSource.class,
Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), dataSource -> { Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), dataSource -> {
assertThat(dataSource.getTestOnBorrow()).isEqualTo(true); assertThat(dataSource.getTestOnBorrow()).isEqualTo(true);
assertThat(dataSource.getValidationQuery()).isNull(); // Use Connection#isValid() assertThat(dataSource.getValidationQuery()).isNull(); // Use
// Connection#isValid()
}); });
} }
...@@ -144,13 +148,14 @@ public class DataSourceAutoConfigurationTests { ...@@ -144,13 +148,14 @@ public class DataSourceAutoConfigurationTests {
public void testEmbeddedTypeDefaultsUsername() throws Exception { public void testEmbeddedTypeDefaultsUsername() throws Exception {
this.contextLoader.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", this.contextLoader.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver",
"spring.datasource.url:jdbc:hsqldb:mem:testdb").load(context -> { "spring.datasource.url:jdbc:hsqldb:mem:testdb").load(context -> {
DataSource bean = context.getBean(DataSource.class); DataSource bean = context.getBean(DataSource.class);
assertThat(bean).isNotNull(); assertThat(bean).isNotNull();
@SuppressWarnings("resource") @SuppressWarnings("resource")
HikariDataSource pool = (HikariDataSource) bean; HikariDataSource pool = (HikariDataSource) bean;
assertThat(pool.getDriverClassName()).isEqualTo("org.hsqldb.jdbcDriver"); assertThat(pool.getDriverClassName())
assertThat(pool.getUsername()).isEqualTo("sa"); .isEqualTo("org.hsqldb.jdbcDriver");
}); assertThat(pool.getUsername()).isEqualTo("sa");
});
} }
/** /**
...@@ -159,24 +164,28 @@ public class DataSourceAutoConfigurationTests { ...@@ -159,24 +164,28 @@ public class DataSourceAutoConfigurationTests {
*/ */
@Test @Test
public void explicitTypeNoSupportedDataSource() { public void explicitTypeNoSupportedDataSource() {
this.contextLoader.classLoader( this.contextLoader
new HidePackagesClassLoader("org.apache.tomcat", "com.zaxxer.hikari", .classLoader(new HidePackagesClassLoader("org.apache.tomcat",
"org.apache.commons.dbcp", "org.apache.commons.dbcp2")) "com.zaxxer.hikari", "org.apache.commons.dbcp",
"org.apache.commons.dbcp2"))
.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", .env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver",
"spring.datasource.url:jdbc:hsqldb:mem:testdb", "spring.datasource.url:jdbc:hsqldb:mem:testdb",
"spring.datasource.type:" + SimpleDriverDataSource.class.getName()) "spring.datasource.type:"
+ SimpleDriverDataSource.class.getName())
.load(testExplicitType()); .load(testExplicitType());
} }
@Test @Test
public void explicitTypeSupportedDataSource() { public void explicitTypeSupportedDataSource() {
this.contextLoader.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", this.contextLoader
"spring.datasource.url:jdbc:hsqldb:mem:testdb", .env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver",
"spring.datasource.type:" + SimpleDriverDataSource.class.getName()) "spring.datasource.url:jdbc:hsqldb:mem:testdb",
"spring.datasource.type:"
+ SimpleDriverDataSource.class.getName())
.load(testExplicitType()); .load(testExplicitType());
} }
private ContextConsumer testExplicitType() { private ContextConsumer<AnnotationConfigApplicationContext> testExplicitType() {
return context -> { return context -> {
assertThat(context.getBeansOfType(DataSource.class)).hasSize(1); assertThat(context.getBeansOfType(DataSource.class)).hasSize(1);
DataSource bean = context.getBean(DataSource.class); DataSource bean = context.getBean(DataSource.class);
...@@ -187,14 +196,15 @@ public class DataSourceAutoConfigurationTests { ...@@ -187,14 +196,15 @@ public class DataSourceAutoConfigurationTests {
@Test @Test
public void testExplicitDriverClassClearsUsername() throws Exception { public void testExplicitDriverClassClearsUsername() throws Exception {
this.contextLoader.env("spring.datasource.driverClassName:" + DatabaseTestDriver.class.getName(), this.contextLoader.env(
"spring.datasource.driverClassName:" + DatabaseTestDriver.class.getName(),
"spring.datasource.url:jdbc:foo://localhost").load(context -> { "spring.datasource.url:jdbc:foo://localhost").load(context -> {
DataSource dataSource = context.getBean(DataSource.class); DataSource dataSource = context.getBean(DataSource.class);
assertThat(dataSource).isNotNull(); assertThat(dataSource).isNotNull();
assertThat(((HikariDataSource) dataSource).getDriverClassName()) assertThat(((HikariDataSource) dataSource).getDriverClassName())
.isEqualTo(DatabaseTestDriver.class.getName()); .isEqualTo(DatabaseTestDriver.class.getName());
assertThat(((HikariDataSource) dataSource).getUsername()).isNull(); assertThat(((HikariDataSource) dataSource).getUsername()).isNull();
}); });
} }
@Test @Test
...@@ -208,22 +218,21 @@ public class DataSourceAutoConfigurationTests { ...@@ -208,22 +218,21 @@ public class DataSourceAutoConfigurationTests {
@Test @Test
public void testDataSourceIsInitializedEarly() { public void testDataSourceIsInitializedEarly() {
this.contextLoader.config(TestInitializedDataSourceConfiguration.class) this.contextLoader.config(TestInitializedDataSourceConfiguration.class)
.env("spring.datasource.initialize=true").load(context -> .env("spring.datasource.initialize=true")
assertThat(context.getBean( .load(context -> assertThat(context
TestInitializedDataSourceConfiguration.class).called).isTrue()); .getBean(TestInitializedDataSourceConfiguration.class).called)
.isTrue());
} }
private <T extends DataSource> void assertDataSource(Class<T> expectedType, private <T extends DataSource> void assertDataSource(Class<T> expectedType,
List<String> hiddenPackages, Consumer<T> consumer) { List<String> hiddenPackages, Consumer<T> consumer) {
HidePackagesClassLoader classLoader = new HidePackagesClassLoader( HidePackagesClassLoader classLoader = new HidePackagesClassLoader(
hiddenPackages.toArray(new String[hiddenPackages.size()])); hiddenPackages.toArray(new String[hiddenPackages.size()]));
this.contextLoader this.contextLoader.classLoader(classLoader).load(context -> {
.classLoader(classLoader) DataSource bean = context.getBean(DataSource.class);
.load(context -> { assertThat(bean).isInstanceOf(expectedType);
DataSource bean = context.getBean(DataSource.class); consumer.accept(expectedType.cast(bean));
assertThat(bean).isInstanceOf(expectedType); });
consumer.accept(expectedType.cast(bean));
});
} }
@Configuration @Configuration
......
...@@ -25,6 +25,7 @@ import org.junit.Test; ...@@ -25,6 +25,7 @@ import org.junit.Test;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -41,60 +42,71 @@ import static org.mockito.Mockito.mockingDetails; ...@@ -41,60 +42,71 @@ import static org.mockito.Mockito.mockingDetails;
*/ */
public class ActiveMQAutoConfigurationTests { public class ActiveMQAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader().autoConfig( private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class); .standard()
.autoConfig(ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class);
@Test @Test
public void brokerIsEmbeddedByDefault() { public void brokerIsEmbeddedByDefault() {
this.contextLoader.config(EmptyConfiguration.class).load(context -> { this.contextLoader.config(EmptyConfiguration.class).load(context -> {
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); ConnectionFactory connectionFactory = context
.getBean(ConnectionFactory.class);
assertThat(connectionFactory).isInstanceOf(ActiveMQConnectionFactory.class); assertThat(connectionFactory).isInstanceOf(ActiveMQConnectionFactory.class);
String brokerUrl = ((ActiveMQConnectionFactory) connectionFactory).getBrokerURL(); String brokerUrl = ((ActiveMQConnectionFactory) connectionFactory)
.getBrokerURL();
assertThat(brokerUrl).isEqualTo("vm://localhost?broker.persistent=false"); assertThat(brokerUrl).isEqualTo("vm://localhost?broker.persistent=false");
}); });
} }
@Test @Test
public void configurationBacksOffWhenCustomConnectionFactoryExists() { public void configurationBacksOffWhenCustomConnectionFactoryExists() {
this.contextLoader.config(CustomConnectionFactoryConfiguration.class).load( this.contextLoader.config(CustomConnectionFactoryConfiguration.class)
context -> assertThat(mockingDetails(context .load(context -> assertThat(
.getBean(ConnectionFactory.class)).isMock()).isTrue()); mockingDetails(context.getBean(ConnectionFactory.class)).isMock())
.isTrue());
} }
@Test @Test
public void customPooledConnectionFactoryConfiguration() { public void customPooledConnectionFactoryConfiguration() {
this.contextLoader.config(EmptyConfiguration.class).env( this.contextLoader.config(EmptyConfiguration.class)
"spring.activemq.pool.enabled:true", .env("spring.activemq.pool.enabled:true",
"spring.activemq.pool.maxConnections:256", "spring.activemq.pool.maxConnections:256",
"spring.activemq.pool.idleTimeout:512", "spring.activemq.pool.idleTimeout:512",
"spring.activemq.pool.expiryTimeout:4096", "spring.activemq.pool.expiryTimeout:4096",
"spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024", "spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024",
"spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048").load(context -> { "spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048")
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); .load(context -> {
assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); ConnectionFactory connectionFactory = context
PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory; .getBean(ConnectionFactory.class);
assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256); assertThat(connectionFactory)
assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512); .isInstanceOf(PooledConnectionFactory.class);
assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection()) PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory;
.isEqualTo(1024); assertThat(pooledConnectionFactory.getMaxConnections())
assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis()) .isEqualTo(256);
.isEqualTo(2048); assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512);
assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096); assertThat(pooledConnectionFactory
}); .getMaximumActiveSessionPerConnection()).isEqualTo(1024);
assertThat(
pooledConnectionFactory.getTimeBetweenExpirationCheckMillis())
.isEqualTo(2048);
assertThat(pooledConnectionFactory.getExpiryTimeout())
.isEqualTo(4096);
});
} }
@Test @Test
public void pooledConnectionFactoryConfiguration() throws JMSException { public void pooledConnectionFactoryConfiguration() throws JMSException {
this.contextLoader.config(EmptyConfiguration.class) this.contextLoader.config(EmptyConfiguration.class)
.env("spring.activemq.pool.enabled:true").load(context -> { .env("spring.activemq.pool.enabled:true").load(context -> {
ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); ConnectionFactory connectionFactory = context
assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); .getBean(ConnectionFactory.class);
context.close(); assertThat(connectionFactory)
assertThat(connectionFactory.createConnection()).isNull(); .isInstanceOf(PooledConnectionFactory.class);
}); context.close();
assertThat(connectionFactory.createConnection()).isNull();
});
} }
@Configuration @Configuration
static class EmptyConfiguration { static class EmptyConfiguration {
......
...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web.reactive; ...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web.reactive;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.HttpHandler;
...@@ -38,8 +39,8 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -38,8 +39,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class HttpHandlerAutoConfigurationTests { public class HttpHandlerAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader().webReactive() private final ContextLoader<GenericReactiveWebApplicationContext> contextLoader = ContextLoader
.autoConfig(HttpHandlerAutoConfiguration.class); .reactiveWeb().autoConfig(HttpHandlerAutoConfiguration.class);
@Test @Test
public void shouldNotProcessIfExistingHttpHandler() { public void shouldNotProcessIfExistingHttpHandler() {
......
...@@ -61,7 +61,7 @@ import org.springframework.validation.Validator; ...@@ -61,7 +61,7 @@ import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.HttpPutFormContentFilter; import org.springframework.web.filter.HttpPutFormContentFilter;
import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerExceptionResolver;
...@@ -114,11 +114,12 @@ public class WebMvcAutoConfigurationTests { ...@@ -114,11 +114,12 @@ public class WebMvcAutoConfigurationTests {
private static final MockServletWebServerFactory webServerFactory = new MockServletWebServerFactory(); private static final MockServletWebServerFactory webServerFactory = new MockServletWebServerFactory();
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigWebApplicationContext> contextLoader = ContextLoader
.servletWeb()
.autoConfig(WebMvcAutoConfiguration.class, .autoConfig(WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class) PropertyPlaceholderAutoConfiguration.class)
.config(Config.class).webServlet(); .config(Config.class);
@Test @Test
public void handlerAdaptersCreated() { public void handlerAdaptersCreated() {
...@@ -574,11 +575,10 @@ public class WebMvcAutoConfigurationTests { ...@@ -574,11 +575,10 @@ public class WebMvcAutoConfigurationTests {
public void welcomePageMappingProducesNotFoundResponseWhenThereIsNoWelcomePage() { public void welcomePageMappingProducesNotFoundResponseWhenThereIsNoWelcomePage() {
this.contextLoader this.contextLoader
.env("spring.resources.static-locations:classpath:/no-welcome-page/"); .env("spring.resources.static-locations:classpath:/no-welcome-page/");
this.contextLoader.webServlet().load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
// TODO This cast is ugly. Fix it with generics and ContextLoader subclasses MockMvcBuilders.webAppContextSetup(context).build()
MockMvcBuilders.webAppContextSetup((WebApplicationContext) context).build()
.perform(get("/").accept(MediaType.TEXT_HTML)) .perform(get("/").accept(MediaType.TEXT_HTML))
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
}); });
...@@ -603,8 +603,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -603,8 +603,7 @@ public class WebMvcAutoConfigurationTests {
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
MockMvc mockMvc = MockMvcBuilders MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
.webAppContextSetup((WebApplicationContext) context).build();
mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)) mockMvc.perform(get("/").accept(MediaType.TEXT_HTML))
.andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); .andExpect(status().isOk()).andExpect(forwardedUrl("index.html"));
mockMvc.perform(get("/").accept("*/*")).andExpect(status().isOk()) mockMvc.perform(get("/").accept("*/*")).andExpect(status().isOk())
...@@ -619,8 +618,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -619,8 +618,7 @@ public class WebMvcAutoConfigurationTests {
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
MockMvc mockMvc = MockMvcBuilders MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
.webAppContextSetup((WebApplicationContext) context).build();
mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
}); });
...@@ -633,8 +631,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -633,8 +631,7 @@ public class WebMvcAutoConfigurationTests {
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
MockMvc mockMvc = MockMvcBuilders MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
.webAppContextSetup((WebApplicationContext) context).build();
mockMvc.perform(get("/")).andExpect(status().isOk()) mockMvc.perform(get("/")).andExpect(status().isOk())
.andExpect(forwardedUrl("index.html")); .andExpect(forwardedUrl("index.html"));
}); });
...@@ -648,8 +645,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -648,8 +645,7 @@ public class WebMvcAutoConfigurationTests {
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
MockMvc mockMvc = MockMvcBuilders MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
.webAppContextSetup((WebApplicationContext) context).build();
mockMvc.perform(get("/").header(HttpHeaders.ACCEPT, "")) mockMvc.perform(get("/").header(HttpHeaders.ACCEPT, ""))
.andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); .andExpect(status().isOk()).andExpect(forwardedUrl("index.html"));
}); });
...@@ -663,8 +659,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -663,8 +659,7 @@ public class WebMvcAutoConfigurationTests {
this.contextLoader.load(context -> { this.contextLoader.load(context -> {
assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(context.getBeansOfType(WelcomePageHandlerMapping.class))
.hasSize(1); .hasSize(1);
MockMvc mockMvc = MockMvcBuilders MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
.webAppContextSetup((WebApplicationContext) context).build();
mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)) mockMvc.perform(get("/").accept(MediaType.TEXT_HTML))
.andExpect(status().isOk()).andExpect(forwardedUrl("index.html")); .andExpect(status().isOk()).andExpect(forwardedUrl("index.html"));
}); });
......
...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.BeanCreationException; ...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -36,8 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -36,8 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class WebServicesAutoConfigurationTests { public class WebServicesAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader().webServlet() private final ContextLoader<AnnotationConfigWebApplicationContext> contextLoader = ContextLoader
.autoConfig(WebServicesAutoConfiguration.class); .servletWeb().autoConfig(WebServicesAutoConfiguration.class);
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
......
...@@ -21,6 +21,7 @@ import javax.sql.DataSource; ...@@ -21,6 +21,7 @@ import javax.sql.DataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
...@@ -37,8 +38,8 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -37,8 +38,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class TestDatabaseAutoConfigurationTests { public class TestDatabaseAutoConfigurationTests {
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.autoConfig(TestDatabaseAutoConfiguration.class); .standard().autoConfig(TestDatabaseAutoConfiguration.class);
@Test @Test
public void replaceWithNoDataSourceAvailable() { public void replaceWithNoDataSourceAvailable() {
......
...@@ -26,6 +26,7 @@ import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfigur ...@@ -26,6 +26,7 @@ import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfigur
import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.test.context.ContextLoader;
import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -43,8 +44,8 @@ import static org.mockito.Mockito.mock; ...@@ -43,8 +44,8 @@ import static org.mockito.Mockito.mock;
@ClassPathExclusions({ "h2-*.jar", "hsqldb-*.jar", "derby-*.jar" }) @ClassPathExclusions({ "h2-*.jar", "hsqldb-*.jar", "derby-*.jar" })
public class TestDatabaseAutoConfigurationNoEmbeddedTests { public class TestDatabaseAutoConfigurationNoEmbeddedTests {
private final ContextLoader contextLoader = new ContextLoader() private final ContextLoader<AnnotationConfigApplicationContext> contextLoader = ContextLoader
.config(ExistingDataSourceConfiguration.class) .standard().config(ExistingDataSourceConfiguration.class)
.autoConfig(TestDatabaseAutoConfiguration.class); .autoConfig(TestDatabaseAutoConfiguration.class);
@Test @Test
......
...@@ -20,22 +20,21 @@ import org.springframework.context.ConfigurableApplicationContext; ...@@ -20,22 +20,21 @@ import org.springframework.context.ConfigurableApplicationContext;
/** /**
* Callback interface used in tests to process a running * Callback interface used in tests to process a running
* {@link ConfigurableApplicationContext} with the ability to throw a (checked) * {@link ConfigurableApplicationContext} with the ability to throw a (checked) exception.
* exception.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0 * @since 2.0.0
* @param <T> the type of the context that can be consumed
*/ */
@FunctionalInterface @FunctionalInterface
public interface ContextConsumer { public interface ContextConsumer<T extends ConfigurableApplicationContext> {
/** /**
* Performs this operation on the supplied {@link ConfigurableApplicationContext * Performs this operation on the supplied {@code context}.
* ApplicationContext}.
* @param context the application context to consume * @param context the application context to consume
* @throws Throwable any exception that might occur in assertions * @throws Throwable any exception that might occur in assertions
*/ */
void accept(ConfigurableApplicationContext context) throws Throwable; void accept(T context) throws Throwable;
} }
/*
* 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.context;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigRegistry;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Standard implementation of {@link ContextLoader}.
*
* @author Stephane Nicoll
* @author Andy Wilkinson
* @param <T> the type of the context to be loaded
*/
final class StandardContextLoader<T extends ConfigurableApplicationContext & AnnotationConfigRegistry>
implements ContextLoader<T> {
private final Map<String, String> systemProperties = new HashMap<>();
private final List<String> env = new ArrayList<>();
private final Set<Class<?>> userConfigurations = new LinkedHashSet<>();
private final LinkedList<Class<?>> autoConfigurations = new LinkedList<>();
private final Supplier<T> contextSupplier;
private ClassLoader classLoader;
StandardContextLoader(Supplier<T> contextSupplier) {
this.contextSupplier = contextSupplier;
}
/**
* Set the specified system property prior to loading the context and restore its
* previous value once the consumer has been invoked and the context closed. If the
* {@code value} is {@code null} this removes any prior customization for that key.
* @param key the system property
* @param value the value (can be null to remove any existing customization)
* @return this instance
*/
@Override
public StandardContextLoader<T> systemProperty(String key, String value) {
Assert.notNull(key, "Key must not be null");
if (value != null) {
this.systemProperties.put(key, value);
}
else {
this.systemProperties.remove(key);
}
return this;
}
/**
* Add the specified property pairs. Key-value pairs can be specified with colon (":")
* or equals ("=") separators. Override matching keys that might have been specified
* previously.
* @param pairs the key-value pairs for properties that need to be added to the
* environment
* @return this instance
*/
@Override
public StandardContextLoader<T> env(String... pairs) {
if (!ObjectUtils.isEmpty(pairs)) {
this.env.addAll(Arrays.asList(pairs));
}
return this;
}
/**
* Add the specified user configuration classes.
* @param configs the user configuration classes to add
* @return this instance
*/
@Override
public StandardContextLoader<T> config(Class<?>... configs) {
if (!ObjectUtils.isEmpty(configs)) {
this.userConfigurations.addAll(Arrays.asList(configs));
}
return this;
}
/**
* Add the specified auto-configuration classes.
* @param autoConfigurations the auto-configuration classes to add
* @return this instance
*/
@Override
public StandardContextLoader<T> autoConfig(Class<?>... autoConfigurations) {
if (!ObjectUtils.isEmpty(autoConfigurations)) {
this.autoConfigurations.addAll(Arrays.asList(autoConfigurations));
}
return this;
}
/**
* Add the specified auto-configurations at the beginning (in that order) so that it
* is applied before any other existing auto-configurations, but after any user
* configuration. If {@code A} and {@code B} are specified, {@code A} will be
* processed, then {@code B} and finally the rest of the existing auto-configuration.
* @param autoConfigurations the auto-configuration to add
* @return this instance
*/
@Override
public StandardContextLoader<T> autoConfigFirst(Class<?>... autoConfigurations) {
this.autoConfigurations.addAll(0, Arrays.asList(autoConfigurations));
return this;
}
/**
* Customize the {@link ClassLoader} that the {@link ApplicationContext} should use.
* Customizing the {@link ClassLoader} is an effective manner to hide resources from
* the classpath.
* @param classLoader the classloader to use (can be null to use the default)
* @return this instance
* @see HidePackagesClassLoader
*/
@Override
public StandardContextLoader<T> classLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
return this;
}
/**
* Create and refresh a new {@link ApplicationContext} based on the current state of
* this loader. The context is consumed by the specified {@link ContextConsumer} and
* closed upon completion.
* @param consumer the consumer of the created {@link ApplicationContext}
*/
@Override
public void load(ContextConsumer<T> consumer) {
try (ApplicationContextLifecycleHandler handler = new ApplicationContextLifecycleHandler()) {
try {
T ctx = handler.load();
consumer.accept(ctx);
}
catch (RuntimeException ex) {
throw ex;
}
catch (Throwable ex) {
throw new IllegalStateException(
"An unexpected error occurred: " + ex.getMessage(), ex);
}
}
}
/**
* Create and refresh a new {@link ApplicationContext} based on the current state of
* this loader that this expected to fail. If the context does not fail, an
* {@link AssertionError} is thrown. Otherwise the exception is consumed by the
* specified {@link Consumer} with no expectation on the type of the exception.
* @param consumer the consumer of the failure
*/
@Override
public void loadAndFail(Consumer<Throwable> consumer) {
loadAndFail(Throwable.class, consumer);
}
/**
* Create and refresh a new {@link ApplicationContext} based on the current state of
* this loader that this expected to fail. If the context does not fail, an
* {@link AssertionError} is thrown. If the exception does not match the specified
* {@code exceptionType}, an {@link AssertionError} is thrown as well. If the
* exception type matches, it is consumed by the specified {@link Consumer}.
* @param exceptionType the expected type of the failure
* @param consumer the consumer of the failure
* @param <E> the expected type of the failure
*/
@Override
public <E extends Throwable> void loadAndFail(Class<E> exceptionType,
Consumer<E> consumer) {
try (ApplicationContextLifecycleHandler handler = new ApplicationContextLifecycleHandler()) {
handler.load();
throw new AssertionError("ApplicationContext should have failed");
}
catch (Throwable ex) {
assertThat(ex).as("Wrong application context failure exception")
.isInstanceOf(exceptionType);
consumer.accept(exceptionType.cast(ex));
}
}
private T configureApplicationContext() {
T context = StandardContextLoader.this.contextSupplier.get();
if (this.classLoader != null) {
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context).setClassLoader(this.classLoader);
}
else {
throw new IllegalStateException("Cannot configure ClassLoader: " + context
+ " is not a DefaultResourceLoader sub-class");
}
}
if (!ObjectUtils.isEmpty(this.env)) {
TestPropertyValues.of(this.env.toArray(new String[this.env.size()]))
.applyTo(context);
}
if (!ObjectUtils.isEmpty(this.userConfigurations)) {
context.register(this.userConfigurations
.toArray(new Class<?>[this.userConfigurations.size()]));
}
if (!ObjectUtils.isEmpty(this.autoConfigurations)) {
LinkedHashSet<Class<?>> linkedHashSet = new LinkedHashSet<>(
this.autoConfigurations);
context.register(
linkedHashSet.toArray(new Class<?>[this.autoConfigurations.size()]));
}
return context;
}
/**
* Handles the lifecycle of the {@link ApplicationContext}.
*/
private class ApplicationContextLifecycleHandler implements Closeable {
private final Map<String, String> customSystemProperties;
private final Map<String, String> previousSystemProperties = new HashMap<>();
private ConfigurableApplicationContext context;
ApplicationContextLifecycleHandler() {
this.customSystemProperties = new HashMap<>(
StandardContextLoader.this.systemProperties);
}
public T load() {
setCustomSystemProperties();
T context = configureApplicationContext();
context.refresh();
this.context = context;
return context;
}
@Override
public void close() {
try {
if (this.context != null) {
this.context.close();
}
}
finally {
unsetCustomSystemProperties();
}
}
private void setCustomSystemProperties() {
this.customSystemProperties.forEach((key, value) -> {
String previous = System.setProperty(key, value);
this.previousSystemProperties.put(key, previous);
});
}
private void unsetCustomSystemProperties() {
this.previousSystemProperties.forEach((key, value) -> {
if (value != null) {
System.setProperty(key, value);
}
else {
System.clearProperty(key);
}
});
}
}
}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.test.rule; package org.springframework.boot.test.context;
import java.util.UUID; import java.util.UUID;
...@@ -24,27 +24,28 @@ import org.junit.Test; ...@@ -24,27 +24,28 @@ import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.boot.test.context.HidePackagesClassLoader;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.test.context.support.AbstractContextLoader;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
/** /**
* Tests for {@link ContextLoader}. * Tests for {@link AbstractContextLoader}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class ContextLoaderTests { public class StandardContextLoaderTests {
@Rule @Rule
public final ExpectedException thrown = ExpectedException.none(); public final ExpectedException thrown = ExpectedException.none();
private final ContextLoader contextLoader = new ContextLoader(); private final StandardContextLoader<AnnotationConfigApplicationContext> contextLoader = new StandardContextLoader<>(
() -> new AnnotationConfigApplicationContext());
@Test @Test
public void systemPropertyIsSetAndRemoved() { public void systemPropertyIsSetAndRemoved() {
...@@ -61,9 +62,9 @@ public class ContextLoaderTests { ...@@ -61,9 +62,9 @@ public class ContextLoaderTests {
public void systemPropertyIsRemovedIfContextFailed() { public void systemPropertyIsRemovedIfContextFailed() {
String key = "test." + UUID.randomUUID().toString(); String key = "test." + UUID.randomUUID().toString();
assertThat(System.getProperties().containsKey(key)).isFalse(); assertThat(System.getProperties().containsKey(key)).isFalse();
this.contextLoader.systemProperty(key, "value") this.contextLoader.systemProperty(key, "value").config(ConfigC.class)
.config(ConfigC.class).loadAndFail(e -> { .loadAndFail(e -> {
}); });
assertThat(System.getProperties().containsKey(key)).isFalse(); assertThat(System.getProperties().containsKey(key)).isFalse();
} }
...@@ -87,10 +88,10 @@ public class ContextLoaderTests { ...@@ -87,10 +88,10 @@ public class ContextLoaderTests {
public void systemPropertyCanBeSetToNullValue() { public void systemPropertyCanBeSetToNullValue() {
String key = "test." + UUID.randomUUID().toString(); String key = "test." + UUID.randomUUID().toString();
assertThat(System.getProperties().containsKey(key)).isFalse(); assertThat(System.getProperties().containsKey(key)).isFalse();
this.contextLoader.systemProperty(key, "value") this.contextLoader.systemProperty(key, "value").systemProperty(key, null)
.systemProperty(key, null).load(context -> { .load(context -> {
assertThat(System.getProperties().containsKey(key)).isFalse(); assertThat(System.getProperties().containsKey(key)).isFalse();
}); });
} }
@Test @Test
...@@ -102,8 +103,8 @@ public class ContextLoaderTests { ...@@ -102,8 +103,8 @@ public class ContextLoaderTests {
@Test @Test
public void envIsAdditive() { public void envIsAdditive() {
this.contextLoader.env("test.foo=1").env("test.bar=2").load(context -> { this.contextLoader.env("test.foo=1").env("test.bar=2").load(context -> {
ConfigurableEnvironment environment = context.getBean( ConfigurableEnvironment environment = context
ConfigurableEnvironment.class); .getBean(ConfigurableEnvironment.class);
assertThat(environment.getProperty("test.foo", Integer.class)).isEqualTo(1); assertThat(environment.getProperty("test.foo", Integer.class)).isEqualTo(1);
assertThat(environment.getProperty("test.bar", Integer.class)).isEqualTo(2); assertThat(environment.getProperty("test.bar", Integer.class)).isEqualTo(2);
}); });
...@@ -111,45 +112,42 @@ public class ContextLoaderTests { ...@@ -111,45 +112,42 @@ public class ContextLoaderTests {
@Test @Test
public void envOverridesExistingKey() { public void envOverridesExistingKey() {
this.contextLoader.env("test.foo=1").env("test.foo=2").load(context -> this.contextLoader.env("test.foo=1").env("test.foo=2")
assertThat(context.getBean(ConfigurableEnvironment.class) .load(context -> assertThat(context.getBean(ConfigurableEnvironment.class)
.getProperty("test.foo", Integer.class)).isEqualTo(2)); .getProperty("test.foo", Integer.class)).isEqualTo(2));
} }
@Test @Test
public void configurationIsProcessedInOrder() { public void configurationIsProcessedInOrder() {
this.contextLoader.config(ConfigA.class, AutoConfigA.class).load(context -> this.contextLoader.config(ConfigA.class, AutoConfigA.class).load(
assertThat(context.getBean("a")).isEqualTo("autoconfig-a")); context -> assertThat(context.getBean("a")).isEqualTo("autoconfig-a"));
} }
@Test @Test
public void configurationIsProcessedBeforeAutoConfiguration() { public void configurationIsProcessedBeforeAutoConfiguration() {
this.contextLoader.autoConfig(AutoConfigA.class) this.contextLoader.autoConfig(AutoConfigA.class).config(ConfigA.class).load(
.config(ConfigA.class).load(context -> context -> assertThat(context.getBean("a")).isEqualTo("autoconfig-a"));
assertThat(context.getBean("a")).isEqualTo("autoconfig-a"));
} }
@Test @Test
public void configurationIsAdditive() { public void configurationIsAdditive() {
this.contextLoader.config(AutoConfigA.class) this.contextLoader.config(AutoConfigA.class).config(AutoConfigB.class)
.config(AutoConfigB.class).load(context -> { .load(context -> {
assertThat(context.containsBean("a")).isTrue(); assertThat(context.containsBean("a")).isTrue();
assertThat(context.containsBean("b")).isTrue(); assertThat(context.containsBean("b")).isTrue();
}); });
} }
@Test @Test
public void autoConfigureFirstIsAppliedProperly() { public void autoConfigureFirstIsAppliedProperly() {
this.contextLoader.autoConfig(ConfigA.class) this.contextLoader.autoConfig(ConfigA.class).autoConfigFirst(AutoConfigA.class)
.autoConfigFirst(AutoConfigA.class).load(context -> .load(context -> assertThat(context.getBean("a")).isEqualTo("a"));
assertThat(context.getBean("a")).isEqualTo("a"));
} }
@Test @Test
public void autoConfigureFirstWithSeveralConfigsIsAppliedProperly() { public void autoConfigureFirstWithSeveralConfigsIsAppliedProperly() {
this.contextLoader.autoConfig(ConfigA.class, ConfigB.class) this.contextLoader.autoConfig(ConfigA.class, ConfigB.class)
.autoConfigFirst(AutoConfigA.class, AutoConfigB.class) .autoConfigFirst(AutoConfigA.class, AutoConfigB.class).load(context -> {
.load(context -> {
assertThat(context.getBean("a")).isEqualTo("a"); assertThat(context.getBean("a")).isEqualTo("a");
assertThat(context.getBean("b")).isEqualTo(1); assertThat(context.getBean("b")).isEqualTo(1);
}); });
...@@ -157,18 +155,18 @@ public class ContextLoaderTests { ...@@ -157,18 +155,18 @@ public class ContextLoaderTests {
@Test @Test
public void autoConfigurationIsAdditive() { public void autoConfigurationIsAdditive() {
this.contextLoader.autoConfig(AutoConfigA.class) this.contextLoader.autoConfig(AutoConfigA.class).autoConfig(AutoConfigB.class)
.autoConfig(AutoConfigB.class).load(context -> { .load(context -> {
assertThat(context.containsBean("a")).isTrue(); assertThat(context.containsBean("a")).isTrue();
assertThat(context.containsBean("b")).isTrue(); assertThat(context.containsBean("b")).isTrue();
}); });
} }
@Test @Test
public void loadAndFailWithExpectedException() { public void loadAndFailWithExpectedException() {
this.contextLoader.config(ConfigC.class) this.contextLoader.config(ConfigC.class).loadAndFail(BeanCreationException.class,
.loadAndFail(BeanCreationException.class, ex -> ex -> assertThat(ex.getMessage())
assertThat(ex.getMessage()).contains("Error creating bean with name 'c'")); .contains("Error creating bean with name 'c'"));
} }
@Test @Test
...@@ -182,16 +180,19 @@ public class ContextLoaderTests { ...@@ -182,16 +180,19 @@ public class ContextLoaderTests {
@Test @Test
public void classLoaderIsUsed() { public void classLoaderIsUsed() {
this.contextLoader.classLoader(new HidePackagesClassLoader( this.contextLoader
Gson.class.getPackage().getName())).load(context -> { .classLoader(
try { new HidePackagesClassLoader(Gson.class.getPackage().getName()))
ClassUtils.forName(Gson.class.getName(), context.getClassLoader()); .load(context -> {
fail("Should have thrown a ClassNotFoundException"); try {
} ClassUtils.forName(Gson.class.getName(),
catch (ClassNotFoundException e) { context.getClassLoader());
// expected fail("Should have thrown a ClassNotFoundException");
} }
}); catch (ClassNotFoundException e) {
// expected
}
});
} }
@Configuration @Configuration
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment