From 18ba414000db66b338dfe3702a189e5b411c7c8e Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 21 Jun 2017 10:02:57 +0200 Subject: [PATCH] Add test helper to manipulate the ApplicationContext This commit adds ContextLoader, a test helper that configures an ApplicationContext that is meant to simulate a particular auto-configuration scenario. The auto-configuration, user configuration and environment can be customized. The loader invokes a ContextConsumer to assert the context and automatically close the context once it is done. Concretely, tests can create a shared field instance of that helper with the shared configuration to increase its visibility and tune the context further in each test. If the context is expected to fail, `loadAndFail` allows to optionally assert the root exception and consume it for further assertions. This commit also migrates some tests to illustrate the practical use of the helper Closes gh-9634 --- .../cache/CacheAutoConfigurationTests.java | 711 ++++++++++-------- ...HazelcastAutoConfigurationClientTests.java | 88 +-- ...HazelcastAutoConfigurationServerTests.java | 133 ++-- .../HazelcastAutoConfigurationTests.java | 33 +- .../DataSourceAutoConfigurationTests.java | 219 +++--- .../jdbc/DataSourceBuilderTests.java | 2 + .../jms/JmsAutoConfigurationTests.java | 481 ++++++------ .../ActiveMQAutoConfigurationTests.java | 78 +- .../ArtemisAutoConfigurationTests.java | 294 ++++---- .../boot/test/context/ContextConsumer.java | 41 + .../boot/test/context/ContextLoader.java | 315 ++++++++ .../context}/HidePackagesClassLoader.java | 14 +- .../boot/test/rule/ContextLoaderTests.java | 236 ++++++ 13 files changed, 1611 insertions(+), 1034 deletions(-) create mode 100644 spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextConsumer.java create mode 100644 spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java rename {spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc => spring-boot-test/src/main/java/org/springframework/boot/test/context}/HidePackagesClassLoader.java (77%) create mode 100644 spring-boot-test/src/test/java/org/springframework/boot/test/rule/ContextLoaderTests.java diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java index c620422324..588ce5aff4 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java @@ -45,7 +45,6 @@ import org.ehcache.jsr107.EhcacheCachingProvider; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.jcache.embedded.JCachingProvider; import org.infinispan.spring.provider.SpringEmbeddedCacheManager; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -56,7 +55,7 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.cache.support.MockCachingProvider; import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.cache.Cache; @@ -73,7 +72,7 @@ import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.jcache.JCacheCacheManager; import org.springframework.cache.support.NoOpCacheManager; import org.springframework.cache.support.SimpleCacheManager; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -101,65 +100,70 @@ public class CacheAutoConfigurationTests { @Rule public final ExpectedException thrown = ExpectedException.none(); - private AnnotationConfigApplicationContext context; - - @After - public void tearDown() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader().autoConfig( + CacheAutoConfiguration.class); @Test public void noEnableCaching() { - load(EmptyConfiguration.class); - this.thrown.expect(NoSuchBeanDefinitionException.class); - this.context.getBean(CacheManager.class); + this.contextLoader.config(EmptyConfiguration.class).load(context -> { + this.thrown.expect(NoSuchBeanDefinitionException.class); + context.getBean(CacheManager.class); + }); } @Test public void cacheManagerBackOff() { - load(CustomCacheManagerConfiguration.class); - ConcurrentMapCacheManager cacheManager = validateCacheManager( - ConcurrentMapCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("custom1"); + this.contextLoader.config(CustomCacheManagerConfiguration.class).load(context -> { + ConcurrentMapCacheManager cacheManager = validateCacheManager(context, + ConcurrentMapCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("custom1"); + }); } @Test public void cacheManagerFromSupportBackOff() { - load(CustomCacheManagerFromSupportConfiguration.class); - ConcurrentMapCacheManager cacheManager = validateCacheManager( - ConcurrentMapCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("custom1"); + this.contextLoader.config(CustomCacheManagerFromSupportConfiguration.class) + .load(context -> { + ConcurrentMapCacheManager cacheManager = validateCacheManager(context, + ConcurrentMapCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("custom1"); + }); } @Test public void cacheResolverFromSupportBackOff() throws Exception { - load(CustomCacheResolverFromSupportConfiguration.class); - this.thrown.expect(NoSuchBeanDefinitionException.class); - this.context.getBean(CacheManager.class); + this.contextLoader.config(CustomCacheResolverFromSupportConfiguration.class) + .load(context -> { + this.thrown.expect(NoSuchBeanDefinitionException.class); + context.getBean(CacheManager.class); + }); } @Test public void customCacheResolverCanBeDefined() throws Exception { - load(SpecificCacheResolverConfiguration.class, "spring.cache.type=simple"); - validateCacheManager(ConcurrentMapCacheManager.class); - assertThat(this.context.getBeansOfType(CacheResolver.class)).hasSize(1); + this.contextLoader.config(SpecificCacheResolverConfiguration.class) + .env("spring.cache.type=simple").load(context -> { + validateCacheManager(context, ConcurrentMapCacheManager.class); + assertThat(context.getBeansOfType(CacheResolver.class)).hasSize(1); + }); } @Test public void notSupportedCachingMode() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("Failed to bind properties under 'spring.cache.type'"); - load(DefaultCacheConfiguration.class, "spring.cache.type=foobar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=foobar").loadAndFail(BeanCreationException.class, + ex -> assertThat(ex.getMessage()).contains( + "Failed to bind properties under 'spring.cache.type'")); } @Test public void simpleCacheExplicit() { - load(DefaultCacheConfiguration.class, "spring.cache.type=simple"); - ConcurrentMapCacheManager cacheManager = validateCacheManager( - ConcurrentMapCacheManager.class); - assertThat(cacheManager.getCacheNames()).isEmpty(); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=simple").load(context -> { + ConcurrentMapCacheManager cacheManager = validateCacheManager(context, + ConcurrentMapCacheManager.class); + assertThat(cacheManager.getCacheNames()).isEmpty(); + }); } @Test @@ -170,30 +174,34 @@ public class CacheAutoConfigurationTests { @Test public void simpleCacheExplicitWithCacheNames() { - load(DefaultCacheConfiguration.class, "spring.cache.type=simple", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - ConcurrentMapCacheManager cacheManager = validateCacheManager( - ConcurrentMapCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=simple", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + ConcurrentMapCacheManager cacheManager = validateCacheManager(context, + ConcurrentMapCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void genericCacheWithCaches() { - load(GenericCacheConfiguration.class); - SimpleCacheManager cacheManager = validateCacheManager(SimpleCacheManager.class); - assertThat(cacheManager.getCache("first")) - .isEqualTo(this.context.getBean("firstCache")); - assertThat(cacheManager.getCache("second")) - .isEqualTo(this.context.getBean("secondCache")); - assertThat(cacheManager.getCacheNames()).hasSize(2); + this.contextLoader.config(GenericCacheConfiguration.class).load(context -> { + SimpleCacheManager cacheManager = validateCacheManager(context, + SimpleCacheManager.class); + assertThat(cacheManager.getCache("first")) + .isEqualTo(context.getBean("firstCache")); + assertThat(cacheManager.getCache("second")) + .isEqualTo(context.getBean("secondCache")); + assertThat(cacheManager.getCacheNames()).hasSize(2); + }); } @Test public void genericCacheExplicit() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("No cache manager could be auto-configured"); - this.thrown.expectMessage("GENERIC"); - load(DefaultCacheConfiguration.class, "spring.cache.type=generic"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=generic").loadAndFail(BeanCreationException.class, + ex -> assertThat(ex.getMessage()).contains( + "No cache manager could be auto-configured", "GENERIC")); } @Test @@ -204,21 +212,26 @@ public class CacheAutoConfigurationTests { @Test public void genericCacheExplicitWithCaches() { - load(GenericCacheConfiguration.class, "spring.cache.type=generic"); - SimpleCacheManager cacheManager = validateCacheManager(SimpleCacheManager.class); - assertThat(cacheManager.getCache("first")) - .isEqualTo(this.context.getBean("firstCache")); - assertThat(cacheManager.getCache("second")) - .isEqualTo(this.context.getBean("secondCache")); - assertThat(cacheManager.getCacheNames()).hasSize(2); + this.contextLoader.config(GenericCacheConfiguration.class) + .env("spring.cache.type=generic").load(context -> { + SimpleCacheManager cacheManager = validateCacheManager(context, + SimpleCacheManager.class); + assertThat(cacheManager.getCache("first")) + .isEqualTo(context.getBean("firstCache")); + assertThat(cacheManager.getCache("second")) + .isEqualTo(context.getBean("secondCache")); + assertThat(cacheManager.getCacheNames()).hasSize(2); + }); } @Test public void couchbaseCacheExplicit() { - load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase"); - CouchbaseCacheManager cacheManager = validateCacheManager( - CouchbaseCacheManager.class); - assertThat(cacheManager.getCacheNames()).isEmpty(); + this.contextLoader.config(CouchbaseCacheConfiguration.class) + .env("spring.cache.type=couchbase").load(context -> { + CouchbaseCacheManager cacheManager = validateCacheManager(context, + CouchbaseCacheManager.class); + assertThat(cacheManager.getCacheNames()).isEmpty(); + }); } @Test @@ -229,40 +242,46 @@ public class CacheAutoConfigurationTests { @Test public void couchbaseCacheExplicitWithCaches() { - load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - CouchbaseCacheManager cacheManager = validateCacheManager( - CouchbaseCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); - Cache cache = cacheManager.getCache("foo"); - assertThat(cache).isInstanceOf(CouchbaseCache.class); - assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(0); - assertThat(((CouchbaseCache) cache).getNativeCache()) - .isEqualTo(this.context.getBean("bucket")); + this.contextLoader.config(CouchbaseCacheConfiguration.class) + .env("spring.cache.type=couchbase", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + CouchbaseCacheManager cacheManager = validateCacheManager(context, + CouchbaseCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + Cache cache = cacheManager.getCache("foo"); + assertThat(cache).isInstanceOf(CouchbaseCache.class); + assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(0); + assertThat(((CouchbaseCache) cache).getNativeCache()) + .isEqualTo(context.getBean("bucket")); + }); } @Test public void couchbaseCacheExplicitWithTtl() { - load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase", - "spring.cache.cacheNames=foo,bar", - "spring.cache.couchbase.expiration=2000"); - CouchbaseCacheManager cacheManager = validateCacheManager( - CouchbaseCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); - Cache cache = cacheManager.getCache("foo"); - assertThat(cache).isInstanceOf(CouchbaseCache.class); - assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(2); - assertThat(((CouchbaseCache) cache).getNativeCache()) - .isEqualTo(this.context.getBean("bucket")); + this.contextLoader.config(CouchbaseCacheConfiguration.class) + .env("spring.cache.type=couchbase", "spring.cache.cacheNames=foo,bar", + "spring.cache.couchbase.expiration=2000").load(context -> { + CouchbaseCacheManager cacheManager = validateCacheManager(context, + CouchbaseCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + Cache cache = cacheManager.getCache("foo"); + assertThat(cache).isInstanceOf(CouchbaseCache.class); + assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(2); + assertThat(((CouchbaseCache) cache).getNativeCache()) + .isEqualTo(context.getBean("bucket")); + }); } @Test public void redisCacheExplicit() { - load(RedisCacheConfiguration.class, "spring.cache.type=redis"); - RedisCacheManager cacheManager = validateCacheManager(RedisCacheManager.class); - assertThat(cacheManager.getCacheNames()).isEmpty(); - assertThat((Boolean) new DirectFieldAccessor(cacheManager) - .getPropertyValue("usePrefix")).isTrue(); + this.contextLoader.config(RedisCacheConfiguration.class) + .env("spring.cache.type=redis").load(context -> { + RedisCacheManager cacheManager = validateCacheManager(context, + RedisCacheManager.class); + assertThat(cacheManager.getCacheNames()).isEmpty(); + assertThat((Boolean) new DirectFieldAccessor(cacheManager) + .getPropertyValue("usePrefix")).isTrue(); + }); } @Test @@ -273,114 +292,139 @@ public class CacheAutoConfigurationTests { @Test public void redisCacheExplicitWithCaches() { - load(RedisCacheConfiguration.class, "spring.cache.type=redis", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - RedisCacheManager cacheManager = validateCacheManager(RedisCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(RedisCacheConfiguration.class) + .env("spring.cache.type=redis", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + RedisCacheManager cacheManager = validateCacheManager(context, + RedisCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void noOpCacheExplicit() { - load(DefaultCacheConfiguration.class, "spring.cache.type=none"); - NoOpCacheManager cacheManager = validateCacheManager(NoOpCacheManager.class); - assertThat(cacheManager.getCacheNames()).isEmpty(); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=none").load(context -> { + NoOpCacheManager cacheManager = validateCacheManager(context, + NoOpCacheManager.class); + assertThat(cacheManager.getCacheNames()).isEmpty(); + }); } @Test public void jCacheCacheNoProviderExplicit() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("No cache manager could be auto-configured"); - this.thrown.expectMessage("JCACHE"); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache").loadAndFail(ex -> { + assertThat(ex).isInstanceOf(BeanCreationException.class); + assertThat(ex.getMessage()).contains( + "No cache manager could be auto-configured", "JCACHE"); + }); } @Test public void jCacheCacheWithProvider() { String cachingProviderFqn = MockCachingProvider.class.getName(); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).isEmpty(); - assertThat(this.context.getBean(javax.cache.CacheManager.class)) - .isEqualTo(cacheManager.getCacheManager()); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", "spring.cache.jcache.provider=" + + cachingProviderFqn).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).isEmpty(); + assertThat(context.getBean(javax.cache.CacheManager.class)) + .isEqualTo(cacheManager.getCacheManager()); + }); } @Test public void jCacheCacheWithCaches() { String cachingProviderFqn = MockCachingProvider.class.getName(); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void jCacheCacheWithCachesAndCustomConfig() { String cachingProviderFqn = MockCachingProvider.class.getName(); - load(JCacheCustomConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=one", "spring.cache.cacheNames[1]=two"); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("one", "two"); - CompleteConfiguration defaultCacheConfiguration = this.context - .getBean(CompleteConfiguration.class); - verify(cacheManager.getCacheManager()).createCache("one", - defaultCacheConfiguration); - verify(cacheManager.getCacheManager()).createCache("two", - defaultCacheConfiguration); + this.contextLoader.config(JCacheCustomConfiguration.class) + .env("spring.cache.type=jcache", "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.cacheNames[0]=one", + "spring.cache.cacheNames[1]=two").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("one", "two"); + CompleteConfiguration defaultCacheConfiguration = context + .getBean(CompleteConfiguration.class); + verify(cacheManager.getCacheManager()).createCache("one", + defaultCacheConfiguration); + verify(cacheManager.getCacheManager()).createCache("two", + defaultCacheConfiguration); + }); } @Test public void jCacheCacheWithExistingJCacheManager() { - load(JCacheCustomCacheManager.class, "spring.cache.type=jcache"); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheManager()) - .isEqualTo(this.context.getBean("customJCacheCacheManager")); + this.contextLoader.config(JCacheCustomCacheManager.class) + .env("spring.cache.type=jcache").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheManager()) + .isEqualTo(context.getBean("customJCacheCacheManager")); + }); } @Test public void jCacheCacheWithUnknownProvider() { String wrongCachingProviderFqn = "org.acme.FooBar"; - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage(wrongCachingProviderFqn); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + wrongCachingProviderFqn); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", "spring.cache.jcache.provider=" + + wrongCachingProviderFqn).loadAndFail(BeanCreationException.class, + ex -> assertThat(ex.getMessage().contains(wrongCachingProviderFqn))); } @Test - public void jCacheCacheWithConfig() throws IOException { + public void jCacheCacheWithConfig() { String cachingProviderFqn = MockCachingProvider.class.getName(); String configLocation = "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml"; - load(JCacheCustomConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.jcache.config=" + configLocation); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - Resource configResource = new ClassPathResource(configLocation); - assertThat(cacheManager.getCacheManager().getURI()) - .isEqualTo(configResource.getURI()); + this.contextLoader.config(JCacheCustomConfiguration.class) + .env("spring.cache.type=jcache", "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.jcache.config=" + configLocation).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + Resource configResource = new ClassPathResource(configLocation); + assertThat(cacheManager.getCacheManager().getURI()) + .isEqualTo(configResource.getURI()); + }); } @Test public void jCacheCacheWithWrongConfig() { String cachingProviderFqn = MockCachingProvider.class.getName(); String configLocation = "org/springframework/boot/autoconfigure/cache/does-not-exist.xml"; - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("does not exist"); - this.thrown.expectMessage(configLocation); - load(JCacheCustomConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.jcache.config=" + configLocation); + this.contextLoader.config(JCacheCustomConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.jcache.config=" + configLocation) + .loadAndFail(BeanCreationException.class, ex -> + assertThat(ex.getMessage()).contains("does not exist", configLocation)); } @Test public void ehcacheCacheWithCaches() { - load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache"); - EhCacheCacheManager cacheManager = validateCacheManager( - EhCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("cacheTest1", "cacheTest2"); - assertThat(this.context.getBean(net.sf.ehcache.CacheManager.class)) - .isEqualTo(cacheManager.getCacheManager()); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=ehcache").load(context -> { + EhCacheCacheManager cacheManager = validateCacheManager(context, + EhCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly( + "cacheTest1", "cacheTest2"); + assertThat(context.getBean(net.sf.ehcache.CacheManager.class)) + .isEqualTo(cacheManager.getCacheManager()); + }); } @Test @@ -391,59 +435,73 @@ public class CacheAutoConfigurationTests { @Test public void ehcacheCacheWithConfig() { - load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache", - "spring.cache.ehcache.config=cache/ehcache-override.xml"); - EhCacheCacheManager cacheManager = validateCacheManager( - EhCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("cacheOverrideTest1", - "cacheOverrideTest2"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=ehcache", + "spring.cache.ehcache.config=cache/ehcache-override.xml") + .load(context -> { + EhCacheCacheManager cacheManager = validateCacheManager(context, + EhCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("cacheOverrideTest1", + "cacheOverrideTest2"); + }); } @Test public void ehcacheCacheWithExistingCacheManager() { - load(EhCacheCustomCacheManager.class, "spring.cache.type=ehcache"); - EhCacheCacheManager cacheManager = validateCacheManager( - EhCacheCacheManager.class); - assertThat(cacheManager.getCacheManager()) - .isEqualTo(this.context.getBean("customEhCacheCacheManager")); + this.contextLoader.config(EhCacheCustomCacheManager.class) + .env("spring.cache.type=ehcache").load(context -> { + EhCacheCacheManager cacheManager = validateCacheManager(context, + EhCacheCacheManager.class); + assertThat(cacheManager.getCacheManager()) + .isEqualTo(context.getBean("customEhCacheCacheManager")); + }); } @Test public void ehcache3AsJCacheWithCaches() { String cachingProviderFqn = EhcacheCachingProvider.class.getName(); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void ehcache3AsJCacheWithConfig() throws IOException { String cachingProviderFqn = EhcacheCachingProvider.class.getName(); String configLocation = "ehcache3.xml"; - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.jcache.config=" + configLocation); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.jcache.config=" + configLocation).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); - Resource configResource = new ClassPathResource(configLocation); - assertThat(cacheManager.getCacheManager().getURI()) - .isEqualTo(configResource.getURI()); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + Resource configResource = new ClassPathResource(configLocation); + assertThat(cacheManager.getCacheManager().getURI()) + .isEqualTo(configResource.getURI()); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void hazelcastCacheExplicit() { - load(new Class[] { HazelcastAutoConfiguration.class, - DefaultCacheConfiguration.class }, "spring.cache.type=hazelcast"); - HazelcastCacheManager cacheManager = validateCacheManager( - HazelcastCacheManager.class); - // NOTE: the hazelcast implementation knows about a cache in a lazy manner. - cacheManager.getCache("defaultCache"); - assertThat(cacheManager.getCacheNames()).containsOnly("defaultCache"); - assertThat(this.context.getBean(HazelcastInstance.class)) - .isEqualTo(cacheManager.getHazelcastInstance()); + this.contextLoader.autoConfigFirst(HazelcastAutoConfiguration.class) + .config(DefaultCacheConfiguration.class) + .env("spring.cache.type=hazelcast").load(context -> { + HazelcastCacheManager cacheManager = validateCacheManager(context, + HazelcastCacheManager.class); + // NOTE: the hazelcast implementation knows about a cache in a lazy manner. + cacheManager.getCache("defaultCache"); + assertThat(cacheManager.getCacheNames()).containsOnly("defaultCache"); + assertThat(context.getBean(HazelcastInstance.class)) + .isEqualTo(cacheManager.getHazelcastInstance()); + }); } @Test @@ -454,41 +512,46 @@ public class CacheAutoConfigurationTests { @Test public void hazelcastCacheWithExistingHazelcastInstance() { - load(HazelcastCustomHazelcastInstance.class, "spring.cache.type=hazelcast"); - HazelcastCacheManager cacheManager = validateCacheManager( - HazelcastCacheManager.class); - assertThat(cacheManager.getHazelcastInstance()) - .isEqualTo(this.context.getBean("customHazelcastInstance")); + this.contextLoader.config(HazelcastCustomHazelcastInstance.class) + .env("spring.cache.type=hazelcast").load(context -> { + HazelcastCacheManager cacheManager = validateCacheManager(context, + HazelcastCacheManager.class); + assertThat(cacheManager.getHazelcastInstance()) + .isEqualTo(context.getBean("customHazelcastInstance")); + }); } @Test public void hazelcastCacheWithHazelcastAutoConfiguration() throws IOException { String hazelcastConfig = "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml"; - load(new Class[] { HazelcastAutoConfiguration.class, - DefaultCacheConfiguration.class }, "spring.cache.type=hazelcast", - "spring.hazelcast.config=" + hazelcastConfig); - HazelcastCacheManager cacheManager = validateCacheManager( - HazelcastCacheManager.class); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(cacheManager.getHazelcastInstance()).isSameAs(hazelcastInstance); - assertThat(hazelcastInstance.getConfig().getConfigurationFile()) - .isEqualTo(new ClassPathResource(hazelcastConfig).getFile()); - assertThat(cacheManager.getCache("foobar")).isNotNull(); - assertThat(cacheManager.getCacheNames()).containsOnly("foobar"); + this.contextLoader.autoConfigFirst(HazelcastAutoConfiguration.class) + .config(DefaultCacheConfiguration.class).env("spring.cache.type=hazelcast", + "spring.hazelcast.config=" + hazelcastConfig).load(context -> { + HazelcastCacheManager cacheManager = validateCacheManager(context, + HazelcastCacheManager.class); + HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); + assertThat(cacheManager.getHazelcastInstance()).isSameAs(hazelcastInstance); + assertThat(hazelcastInstance.getConfig().getConfigurationFile()) + .isEqualTo(new ClassPathResource(hazelcastConfig).getFile()); + assertThat(cacheManager.getCache("foobar")).isNotNull(); + assertThat(cacheManager.getCacheNames()).containsOnly("foobar"); + }); } @Test public void hazelcastAsJCacheWithCaches() { String cachingProviderFqn = HazelcastCachingProvider.class.getName(); try { - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - JCacheCacheManager cacheManager = validateCacheManager( - JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); - assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + }); } finally { Caching.getCachingProvider(cachingProviderFqn).close(); @@ -500,16 +563,18 @@ public class CacheAutoConfigurationTests { String cachingProviderFqn = HazelcastCachingProvider.class.getName(); try { String configLocation = "org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml"; - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.jcache.config=" + configLocation); - JCacheCacheManager cacheManager = validateCacheManager( - JCacheCacheManager.class); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.jcache.config=" + configLocation).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); - Resource configResource = new ClassPathResource(configLocation); - assertThat(cacheManager.getCacheManager().getURI()) - .isEqualTo(configResource.getURI()); - assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + Resource configResource = new ClassPathResource(configLocation); + assertThat(cacheManager.getCacheManager().getURI()) + .isEqualTo(configResource.getURI()); + assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + }); } finally { Caching.getCachingProvider(cachingProviderFqn).close(); @@ -519,29 +584,32 @@ public class CacheAutoConfigurationTests { @Test public void hazelcastAsJCacheWithExistingHazelcastInstance() throws IOException { String cachingProviderFqn = HazelcastCachingProvider.class.getName(); - load(new Class[] { HazelcastAutoConfiguration.class, - DefaultCacheConfiguration.class }, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - javax.cache.CacheManager jCacheManager = cacheManager.getCacheManager(); - assertThat(jCacheManager) - .isInstanceOf(com.hazelcast.cache.HazelcastCacheManager.class); - assertThat(this.context.getBeansOfType(HazelcastInstance.class)).hasSize(1); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(((com.hazelcast.cache.HazelcastCacheManager) jCacheManager) - .getHazelcastInstance()).isSameAs(hazelcastInstance); - assertThat(hazelcastInstance.getName()).isEqualTo("default-instance"); - assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + this.contextLoader.autoConfig(HazelcastAutoConfiguration.class) + .config(DefaultCacheConfiguration.class).env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + javax.cache.CacheManager jCacheManager = cacheManager.getCacheManager(); + assertThat(jCacheManager) + .isInstanceOf(com.hazelcast.cache.HazelcastCacheManager.class); + assertThat(context.getBeansOfType(HazelcastInstance.class)).hasSize(1); + HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); + assertThat(((com.hazelcast.cache.HazelcastCacheManager) jCacheManager) + .getHazelcastInstance()).isSameAs(hazelcastInstance); + assertThat(hazelcastInstance.getName()).isEqualTo("default-instance"); + assertThat(Hazelcast.getAllHazelcastInstances()).hasSize(1); + }); } @Test public void infinispanCacheWithConfig() { - load(DefaultCacheConfiguration.class, "spring.cache.type=infinispan", - "spring.cache.infinispan.config=infinispan.xml"); - SpringEmbeddedCacheManager cacheManager = validateCacheManager( - SpringEmbeddedCacheManager.class); - assertThat(cacheManager.getCacheNames()).contains("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=infinispan", + "spring.cache.infinispan.config=infinispan.xml").load(context -> { + SpringEmbeddedCacheManager cacheManager = validateCacheManager(context, + SpringEmbeddedCacheManager.class); + assertThat(cacheManager.getCacheNames()).contains("foo", "bar"); + }); } @Test @@ -552,60 +620,74 @@ public class CacheAutoConfigurationTests { @Test public void infinispanCacheWithCaches() { - load(DefaultCacheConfiguration.class, "spring.cache.type=infinispan", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - SpringEmbeddedCacheManager cacheManager = validateCacheManager( - SpringEmbeddedCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=infinispan", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + SpringEmbeddedCacheManager cacheManager = validateCacheManager(context, + SpringEmbeddedCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void infinispanCacheWithCachesAndCustomConfig() { - load(InfinispanCustomConfiguration.class, "spring.cache.type=infinispan", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - SpringEmbeddedCacheManager cacheManager = validateCacheManager( - SpringEmbeddedCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); - ConfigurationBuilder defaultConfigurationBuilder = this.context - .getBean(ConfigurationBuilder.class); - verify(defaultConfigurationBuilder, times(2)).build(); + this.contextLoader.config(InfinispanCustomConfiguration.class) + .env("spring.cache.type=infinispan", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + SpringEmbeddedCacheManager cacheManager = validateCacheManager(context, + SpringEmbeddedCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + ConfigurationBuilder defaultConfigurationBuilder = context + .getBean(ConfigurationBuilder.class); + verify(defaultConfigurationBuilder, times(2)).build(); + }); } @Test public void infinispanAsJCacheWithCaches() { String cachingProviderFqn = JCachingProvider.class.getName(); - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); + }); } @Test public void infinispanAsJCacheWithConfig() throws IOException { String cachingProviderFqn = JCachingProvider.class.getName(); String configLocation = "infinispan.xml"; - load(DefaultCacheConfiguration.class, "spring.cache.type=jcache", - "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.jcache.config=" + configLocation); - JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=jcache", + "spring.cache.jcache.provider=" + cachingProviderFqn, + "spring.cache.jcache.config=" + configLocation).load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); - Resource configResource = new ClassPathResource(configLocation); - assertThat(cacheManager.getCacheManager().getURI()) - .isEqualTo(configResource.getURI()); + Resource configResource = new ClassPathResource(configLocation); + assertThat(cacheManager.getCacheManager().getURI()) + .isEqualTo(configResource.getURI()); + }); } @Test public void jCacheCacheWithCachesAndCustomizer() { String cachingProviderFqn = HazelcastCachingProvider.class.getName(); try { - load(JCacheWithCustomizerConfiguration.class, "spring.cache.type=jcache", + this.contextLoader.config(JCacheWithCustomizerConfiguration.class).env( + "spring.cache.type=jcache", "spring.cache.jcache.provider=" + cachingProviderFqn, - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - JCacheCacheManager cacheManager = validateCacheManager( - JCacheCacheManager.class); - // see customizer - assertThat(cacheManager.getCacheNames()).containsOnly("foo", "custom1"); + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar").load(context -> { + JCacheCacheManager cacheManager = validateCacheManager(context, + JCacheCacheManager.class); + // see customizer + assertThat(cacheManager.getCacheNames()).containsOnly("foo", "custom1"); + }); } finally { Caching.getCachingProvider(cachingProviderFqn).close(); @@ -614,16 +696,18 @@ public class CacheAutoConfigurationTests { @Test public void caffeineCacheWithExplicitCaches() { - load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine", - "spring.cache.cacheNames=foo"); - CaffeineCacheManager cacheManager = validateCacheManager( - CaffeineCacheManager.class); - assertThat(cacheManager.getCacheNames()).containsOnly("foo"); - Cache foo = cacheManager.getCache("foo"); - foo.get("1"); - // See next tests: no spec given so stats should be disabled - assertThat(((CaffeineCache) foo).getNativeCache().stats().missCount()) - .isEqualTo(0L); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=caffeine", + "spring.cache.cacheNames=foo").load(context -> { + CaffeineCacheManager cacheManager = validateCacheManager(context, + CaffeineCacheManager.class); + assertThat(cacheManager.getCacheNames()).containsOnly("foo"); + Cache foo = cacheManager.getCache("foo"); + foo.get("1"); + // See next tests: no spec given so stats should be disabled + assertThat(((CaffeineCache) foo).getNativeCache().stats().missCount()) + .isEqualTo(0L); + }); } @Test @@ -634,28 +718,31 @@ public class CacheAutoConfigurationTests { @Test public void caffeineCacheWithExplicitCacheBuilder() { - load(CaffeineCacheBuilderConfiguration.class, "spring.cache.type=caffeine", - "spring.cache.cacheNames=foo,bar"); - validateCaffeineCacheWithStats(); + this.contextLoader.config(CaffeineCacheBuilderConfiguration.class).env( + "spring.cache.type=caffeine", "spring.cache.cacheNames=foo,bar") + .load(this::validateCaffeineCacheWithStats); } @Test public void caffeineCacheExplicitWithSpec() { - load(CaffeineCacheSpecConfiguration.class, "spring.cache.type=caffeine", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - validateCaffeineCacheWithStats(); + this.contextLoader.config(CaffeineCacheSpecConfiguration.class).env( + "spring.cache.type=caffeine", "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar") + .load(this::validateCaffeineCacheWithStats); } @Test public void caffeineCacheExplicitWithSpecString() { - load(DefaultCacheConfiguration.class, "spring.cache.type=caffeine", - "spring.cache.caffeine.spec=recordStats", - "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); - validateCaffeineCacheWithStats(); + this.contextLoader.config(DefaultCacheConfiguration.class) + .env("spring.cache.type=caffeine", + "spring.cache.caffeine.spec=recordStats", + "spring.cache.cacheNames[0]=foo", + "spring.cache.cacheNames[1]=bar") + .load(this::validateCaffeineCacheWithStats); } - private void validateCaffeineCacheWithStats() { - CaffeineCacheManager cacheManager = validateCacheManager( + private void validateCaffeineCacheWithStats(ConfigurableApplicationContext context) { + CaffeineCacheManager cacheManager = validateCacheManager(context, CaffeineCacheManager.class); assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); Cache foo = cacheManager.getCache("foo"); @@ -664,8 +751,9 @@ public class CacheAutoConfigurationTests { .isEqualTo(1L); } - private T validateCacheManager(Class type) { - CacheManager cacheManager = this.context.getBean(CacheManager.class); + private T validateCacheManager( + ConfigurableApplicationContext context, Class type) { + CacheManager cacheManager = context.getBean(CacheManager.class); assertThat(cacheManager).as("Wrong cache manager type").isInstanceOf(type); return type.cast(cacheManager); } @@ -673,35 +761,24 @@ public class CacheAutoConfigurationTests { @SuppressWarnings("rawtypes") private void testCustomizers(Class config, String cacheType, String... expectedCustomizerNames) { - load(config, "spring.cache.type=" + cacheType); - CacheManager cacheManager = validateCacheManager(CacheManager.class); - List expected = new ArrayList<>(); - expected.addAll(Arrays.asList(expectedCustomizerNames)); - Map map = this.context - .getBeansOfType(CacheManagerTestCustomizer.class); - for (Map.Entry entry : map.entrySet()) { - if (expected.contains(entry.getKey())) { - expected.remove(entry.getKey()); - assertThat(entry.getValue().cacheManager).isSameAs(cacheManager); + this.contextLoader.config(config) + .env("spring.cache.type=" + cacheType).load(context -> { + CacheManager cacheManager = validateCacheManager(context, CacheManager.class); + List expected = new ArrayList<>(); + expected.addAll(Arrays.asList(expectedCustomizerNames)); + Map map = context + .getBeansOfType(CacheManagerTestCustomizer.class); + for (Map.Entry entry : map.entrySet()) { + if (expected.contains(entry.getKey())) { + expected.remove(entry.getKey()); + assertThat(entry.getValue().cacheManager).isSameAs(cacheManager); + } + else { + assertThat(entry.getValue().cacheManager).isNull(); + } } - else { - assertThat(entry.getValue().cacheManager).isNull(); - } - } - assertThat(expected).hasSize(0); - } - - private void load(Class config, String... environment) { - load(new Class[] { config }, environment); - } - - private void load(Class[] configs, String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - TestPropertyValues.of(environment).applyTo(applicationContext); - applicationContext.register(configs); - applicationContext.register(CacheAutoConfiguration.class); - applicationContext.refresh(); - this.context = applicationContext; + assertThat(expected).hasSize(0); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java index cec3d722c6..8664db32e0 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java @@ -23,16 +23,12 @@ import com.hazelcast.client.impl.HazelcastClientProxy; import com.hazelcast.config.Config; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; -import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanCreationException; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,11 +42,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class HazelcastAutoConfigurationClientTests { - @Rule - public final ExpectedException thrown = ExpectedException.none(); - - private AnnotationConfigApplicationContext context; - /** * Servers the test clients will connect to. */ @@ -68,78 +59,57 @@ public class HazelcastAutoConfigurationClientTests { } } - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(HazelcastAutoConfiguration.class); @Test public void systemProperty() throws IOException { - System.setProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY, + this.contextLoader.systemProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY, "classpath:org/springframework/boot/autoconfigure/hazelcast/" - + "hazelcast-client-specific.xml"); - try { - load(); - HazelcastInstance hazelcastInstance = this.context + + "hazelcast-client-specific.xml").load(context -> { + HazelcastInstance hazelcastInstance = context .getBean(HazelcastInstance.class); assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); - } - finally { - System.clearProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY); - } + }); } @Test public void explicitConfigFile() throws IOException { - load("spring.hazelcast.config=org/springframework/boot/autoconfigure/" - + "hazelcast/hazelcast-client-specific.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); - assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); + this.contextLoader.env("spring.hazelcast.config=org/springframework/boot/autoconfigure/" + + "hazelcast/hazelcast-client-specific.xml").load(context -> { + HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); + assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); + assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); + }); } @Test public void explicitConfigUrl() throws IOException { - load("spring.hazelcast.config=hazelcast-client-default.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); - assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); + this.contextLoader.env("spring.hazelcast.config=hazelcast-client-default.xml") + .load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); + assertThat(hazelcastInstance.getName()).startsWith("hz.client_"); + }); } @Test public void unknownConfigFile() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("foo/bar/unknown.xml"); - load("spring.hazelcast.config=foo/bar/unknown.xml"); + this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml") + .loadAndFail(BeanCreationException.class, ex -> + assertThat(ex.getMessage()).contains("foo/bar/unknown.xml")); } @Test public void clientConfigTakesPrecedence() { - load(HazelcastServerAndClientConfig.class, - "spring.hazelcast.config=this-is-ignored.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); - } - - private void load(String... environment) { - load(null, environment); - } - - private void load(Class config, String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - TestPropertyValues.of(environment).applyTo(applicationContext); - if (config != null) { - applicationContext.register(config); - } - applicationContext.register(HazelcastAutoConfiguration.class); - applicationContext.refresh(); - this.context = applicationContext; + this.contextLoader.config(HazelcastServerAndClientConfig.class) + .env("spring.hazelcast.config=this-is-ignored.xml").load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java index 078648f87f..cabb4cab1c 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java @@ -23,17 +23,13 @@ import com.hazelcast.config.Config; import com.hazelcast.config.QueueConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; -import org.junit.After; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.springframework.beans.factory.BeanCreationException; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; 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.Configuration; import org.springframework.core.io.ClassPathResource; @@ -49,69 +45,62 @@ import static org.assertj.core.api.Assertions.assertThat; @ClassPathExclusions("hazelcast-client-*.jar") public class HazelcastAutoConfigurationServerTests { - @Rule - public final ExpectedException thrown = ExpectedException.none(); - - private AnnotationConfigApplicationContext context; - - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(HazelcastAutoConfiguration.class); @Test public void defaultConfigFile() throws IOException { - load(); // hazelcast.xml present in root classpath - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) - .isEqualTo(new ClassPathResource("hazelcast.xml").getURL()); + // hazelcast.xml present in root classpath + this.contextLoader.load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) + .isEqualTo(new ClassPathResource("hazelcast.xml").getURL()); + }); } @Test public void systemProperty() throws IOException { - System.setProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY, - "classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml"); - try { - load(); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - Map queueConfigs = hazelcastInstance.getConfig() - .getQueueConfigs(); - assertThat(queueConfigs).hasSize(1).containsKey("foobar"); - } - finally { - System.clearProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY); - } + this.contextLoader.systemProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY, + "classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml") + .load(context -> { + + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + Map queueConfigs = hazelcastInstance.getConfig() + .getQueueConfigs(); + assertThat(queueConfigs).hasSize(1).containsKey("foobar"); + }); } @Test public void explicitConfigFile() throws IOException { - load("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" - + "hazelcast-specific.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance.getConfig().getConfigurationFile()).isEqualTo( - new ClassPathResource("org/springframework/boot/autoconfigure/hazelcast" - + "/hazelcast-specific.xml").getFile()); + this.contextLoader.env("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/" + + "hazelcast-specific.xml").load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance.getConfig().getConfigurationFile()).isEqualTo( + new ClassPathResource("org/springframework/boot/autoconfigure/hazelcast" + + "/hazelcast-specific.xml").getFile()); + }); } @Test public void explicitConfigUrl() throws IOException { - load("spring.hazelcast.config=hazelcast-default.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) - .isEqualTo(new ClassPathResource("hazelcast-default.xml").getURL()); + this.contextLoader + .env("spring.hazelcast.config=hazelcast-default.xml").load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) + .isEqualTo(new ClassPathResource("hazelcast-default.xml").getURL()); + }); } @Test public void unknownConfigFile() { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("foo/bar/unknown.xml"); - load("spring.hazelcast.config=foo/bar/unknown.xml"); + this.contextLoader.env("spring.hazelcast.config=foo/bar/unknown.xml") + .loadAndFail(BeanCreationException.class, ex -> + assertThat(ex.getMessage()).contains("foo/bar/unknown.xml")); } @Test @@ -120,14 +109,15 @@ public class HazelcastAutoConfigurationServerTests { HazelcastInstance existingHazelcastInstance = Hazelcast .newHazelcastInstance(config); try { - load(HazelcastConfigWithName.class, - "spring.hazelcast.config=this-is-ignored.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance.getConfig().getInstanceName()) - .isEqualTo("my-test-instance"); - // Should reuse any existing instance by default. - assertThat(hazelcastInstance).isEqualTo(existingHazelcastInstance); + this.contextLoader.config(HazelcastConfigWithName.class).env( + "spring.hazelcast.config=this-is-ignored.xml").load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + assertThat(hazelcastInstance.getConfig().getInstanceName()) + .isEqualTo("my-test-instance"); + // Should reuse any existing instance by default. + assertThat(hazelcastInstance).isEqualTo(existingHazelcastInstance); + }); } finally { existingHazelcastInstance.shutdown(); @@ -136,27 +126,14 @@ public class HazelcastAutoConfigurationServerTests { @Test public void configInstanceWithoutName() { - load(HazelcastConfigNoName.class, "spring.hazelcast.config=this-is-ignored.xml"); - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - Map queueConfigs = hazelcastInstance.getConfig() - .getQueueConfigs(); - assertThat(queueConfigs).hasSize(1).containsKey("another-queue"); - } - - private void load(String... environment) { - load(null, environment); - } - - private void load(Class config, String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - TestPropertyValues.of(environment).applyTo(applicationContext); - if (config != null) { - applicationContext.register(config); - } - applicationContext.register(HazelcastAutoConfiguration.class); - applicationContext.refresh(); - this.context = applicationContext; + this.contextLoader.config(HazelcastConfigNoName.class) + .env("spring.hazelcast.config=this-is-ignored.xml").load(context -> { + HazelcastInstance hazelcastInstance = context + .getBean(HazelcastInstance.class); + Map queueConfigs = hazelcastInstance.getConfig() + .getQueueConfigs(); + assertThat(queueConfigs).hasSize(1).containsKey("another-queue"); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java index f47b4bbe26..1371c8f95a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java @@ -19,11 +19,9 @@ package org.springframework.boot.autoconfigure.hazelcast; import java.io.IOException; import com.hazelcast.core.HazelcastInstance; -import org.junit.After; import org.junit.Test; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.core.io.ClassPathResource; import static org.assertj.core.api.Assertions.assertThat; @@ -35,30 +33,17 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class HazelcastAutoConfigurationTests { - private AnnotationConfigApplicationContext context; - - @After - public void closeContext() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(HazelcastAutoConfiguration.class); @Test public void defaultConfigFile() throws IOException { - load(); // no hazelcast-client.xml and hazelcast.xml is present in root classpath - HazelcastInstance hazelcastInstance = this.context - .getBean(HazelcastInstance.class); - assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) - .isEqualTo(new ClassPathResource("hazelcast.xml").getURL()); - } - - private void load(String... environment) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - TestPropertyValues.of(environment).applyTo(ctx); - ctx.register(HazelcastAutoConfiguration.class); - ctx.refresh(); - this.context = ctx; + // no hazelcast-client.xml and hazelcast.xml is present in root classpath + this.contextLoader.load(context -> { + HazelcastInstance hazelcastInstance = context.getBean(HazelcastInstance.class); + assertThat(hazelcastInstance.getConfig().getConfigurationUrl()) + .isEqualTo(new ClassPathResource("hazelcast.xml").getURL()); + }); } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java index e933037076..7294e80b77 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java @@ -21,25 +21,26 @@ import java.sql.Driver; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Properties; import java.util.Random; +import java.util.function.Consumer; import java.util.logging.Logger; import javax.sql.DataSource; import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.dbcp2.BasicDataSource; -import org.junit.After; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.jdbc.DatabaseDriver; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextConsumer; +import org.springframework.boot.test.context.ContextLoader; +import org.springframework.boot.test.context.HidePackagesClassLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; @@ -56,38 +57,33 @@ import static org.mockito.Mockito.mock; */ public class DataSourceAutoConfigurationTests { - @Rule - public final ExpectedException thrown = ExpectedException.none(); - - private ConfigurableApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader() + .autoConfig(DataSourceAutoConfiguration.class) + .env("spring.datasource.initialize=false", + "spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()); @Test public void testDefaultDataSourceExists() throws Exception { - load(); - assertThat(this.context.getBean(DataSource.class)).isNotNull(); + this.contextLoader.load(context -> + assertThat(context.getBean(DataSource.class)).isNotNull()); } @Test public void testDataSourceHasEmbeddedDefault() throws Exception { - load(); - HikariDataSource dataSource = this.context.getBean(HikariDataSource.class); - assertThat(dataSource.getJdbcUrl()).isNotNull(); - assertThat(dataSource.getDriverClassName()).isNotNull(); + this.contextLoader.load(context -> { + HikariDataSource dataSource = context.getBean(HikariDataSource.class); + assertThat(dataSource.getJdbcUrl()).isNotNull(); + assertThat(dataSource.getDriverClassName()).isNotNull(); + }); } @Test public void testBadUrl() throws Exception { try { EmbeddedDatabaseConnection.override = EmbeddedDatabaseConnection.NONE; - this.thrown.expect(BeanCreationException.class); - load("spring.datasource.url:jdbc:not-going-to-work"); + this.contextLoader.env("spring.datasource.url:jdbc:not-going-to-work") + .loadAndFail(BeanCreationException.class, ex -> { + }); } finally { EmbeddedDatabaseConnection.override = null; @@ -96,61 +92,65 @@ public class DataSourceAutoConfigurationTests { @Test public void testBadDriverClass() throws Exception { - this.thrown.expect(BeanCreationException.class); - this.thrown.expectMessage("org.none.jdbcDriver"); - load("spring.datasource.driverClassName:org.none.jdbcDriver"); + this.contextLoader.env("spring.datasource.driverClassName:org.none.jdbcDriver") + .loadAndFail(BeanCreationException.class, ex -> + assertThat(ex.getMessage()).contains("org.none.jdbcDriver")); } @Test public void hikariValidatesConnectionByDefault() throws Exception { - HikariDataSource dataSource = autoConfigureDataSource(HikariDataSource.class, - "org.apache.tomcat"); - assertThat(dataSource.getConnectionTestQuery()).isNull(); - // Use Connection#isValid() + assertDataSource(HikariDataSource.class, + Collections.singletonList("org.apache.tomcat"), + dataSource -> + // Use Connection#isValid() + assertThat(dataSource.getConnectionTestQuery()).isNull() + ); } @Test public void tomcatIsFallback() throws Exception { - org.apache.tomcat.jdbc.pool.DataSource dataSource = autoConfigureDataSource( - org.apache.tomcat.jdbc.pool.DataSource.class, "com.zaxxer.hikari"); - assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb"); + assertDataSource(org.apache.tomcat.jdbc.pool.DataSource.class, + Collections.singletonList("com.zaxxer.hikari"), dataSource -> + assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb")); } @Test public void tomcatValidatesConnectionByDefault() { - org.apache.tomcat.jdbc.pool.DataSource dataSource = autoConfigureDataSource( - org.apache.tomcat.jdbc.pool.DataSource.class, "com.zaxxer.hikari"); - assertThat(dataSource.isTestOnBorrow()).isTrue(); - assertThat(dataSource.getValidationQuery()) - .isEqualTo(DatabaseDriver.HSQLDB.getValidationQuery()); + assertDataSource(org.apache.tomcat.jdbc.pool.DataSource.class, + Collections.singletonList("com.zaxxer.hikari"), dataSource -> { + assertThat(dataSource.isTestOnBorrow()).isTrue(); + assertThat(dataSource.getValidationQuery()) + .isEqualTo(DatabaseDriver.HSQLDB.getValidationQuery()); + }); } @Test public void commonsDbcp2IsFallback() throws Exception { - BasicDataSource dataSource = autoConfigureDataSource(BasicDataSource.class, - "com.zaxxer.hikari", "org.apache.tomcat"); - assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb"); + assertDataSource(BasicDataSource.class, + Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), dataSource -> + assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:testdb")); } @Test public void commonsDbcp2ValidatesConnectionByDefault() throws Exception { - org.apache.commons.dbcp2.BasicDataSource dataSource = autoConfigureDataSource( - org.apache.commons.dbcp2.BasicDataSource.class, "com.zaxxer.hikari", - "org.apache.tomcat"); - assertThat(dataSource.getTestOnBorrow()).isEqualTo(true); - assertThat(dataSource.getValidationQuery()).isNull(); // Use Connection#isValid() + assertDataSource(org.apache.commons.dbcp2.BasicDataSource.class, + Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), dataSource -> { + assertThat(dataSource.getTestOnBorrow()).isEqualTo(true); + assertThat(dataSource.getValidationQuery()).isNull(); // Use Connection#isValid() + }); } @Test public void testEmbeddedTypeDefaultsUsername() throws Exception { - load("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", - "spring.datasource.url:jdbc:hsqldb:mem:testdb"); - DataSource bean = this.context.getBean(DataSource.class); - assertThat(bean).isNotNull(); - @SuppressWarnings("resource") - HikariDataSource pool = (HikariDataSource) bean; - assertThat(pool.getDriverClassName()).isEqualTo("org.hsqldb.jdbcDriver"); - assertThat(pool.getUsername()).isEqualTo("sa"); + this.contextLoader.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", + "spring.datasource.url:jdbc:hsqldb:mem:testdb").load(context -> { + DataSource bean = context.getBean(DataSource.class); + assertThat(bean).isNotNull(); + @SuppressWarnings("resource") + HikariDataSource pool = (HikariDataSource) bean; + assertThat(pool.getDriverClassName()).isEqualTo("org.hsqldb.jdbcDriver"); + assertThat(pool.getUsername()).isEqualTo("sa"); + }); } /** @@ -159,90 +159,71 @@ public class DataSourceAutoConfigurationTests { */ @Test public void explicitTypeNoSupportedDataSource() { - load(null, new HidePackagesClassLoader("org.apache.tomcat", "com.zaxxer.hikari", - "org.apache.commons.dbcp", "org.apache.commons.dbcp2"), - "spring.datasource.driverClassName:org.hsqldb.jdbcDriver", - "spring.datasource.url:jdbc:hsqldb:mem:testdb", - "spring.datasource.type:" - + SimpleDriverDataSource.class.getName()); - testExplicitType(); + this.contextLoader.classLoader( + new HidePackagesClassLoader("org.apache.tomcat", "com.zaxxer.hikari", + "org.apache.commons.dbcp", "org.apache.commons.dbcp2")) + .env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", + "spring.datasource.url:jdbc:hsqldb:mem:testdb", + "spring.datasource.type:" + SimpleDriverDataSource.class.getName()) + .load(testExplicitType()); } @Test public void explicitTypeSupportedDataSource() { - load("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", + this.contextLoader.env("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", "spring.datasource.url:jdbc:hsqldb:mem:testdb", - "spring.datasource.type:" - + SimpleDriverDataSource.class.getName()); - testExplicitType(); + "spring.datasource.type:" + SimpleDriverDataSource.class.getName()) + .load(testExplicitType()); } - private void testExplicitType() { - assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(1); - DataSource bean = this.context.getBean(DataSource.class); - assertThat(bean).isNotNull(); - assertThat(bean.getClass()).isEqualTo(SimpleDriverDataSource.class); + private ContextConsumer testExplicitType() { + return context -> { + assertThat(context.getBeansOfType(DataSource.class)).hasSize(1); + DataSource bean = context.getBean(DataSource.class); + assertThat(bean).isNotNull(); + assertThat(bean.getClass()).isEqualTo(SimpleDriverDataSource.class); + }; } @Test public void testExplicitDriverClassClearsUsername() throws Exception { - load("spring.datasource.driverClassName:" + DatabaseTestDriver.class.getName(), - "spring.datasource.url:jdbc:foo://localhost"); - DataSource dataSource = this.context.getBean(DataSource.class); - assertThat(dataSource).isNotNull(); - assertThat(((HikariDataSource) dataSource).getDriverClassName()) - .isEqualTo(DatabaseTestDriver.class.getName()); - assertThat(((HikariDataSource) dataSource).getUsername()).isNull(); + this.contextLoader.env("spring.datasource.driverClassName:" + DatabaseTestDriver.class.getName(), + "spring.datasource.url:jdbc:foo://localhost").load(context -> { + DataSource dataSource = context.getBean(DataSource.class); + assertThat(dataSource).isNotNull(); + assertThat(((HikariDataSource) dataSource).getDriverClassName()) + .isEqualTo(DatabaseTestDriver.class.getName()); + assertThat(((HikariDataSource) dataSource).getUsername()).isNull(); + }); } @Test public void testDefaultDataSourceCanBeOverridden() throws Exception { - load(TestDataSourceConfiguration.class); - DataSource dataSource = this.context.getBean(DataSource.class); - assertThat(dataSource).isInstanceOf(BasicDataSource.class); + this.contextLoader.config(TestDataSourceConfiguration.class).load(context -> { + DataSource dataSource = context.getBean(DataSource.class); + assertThat(dataSource).isInstanceOf(BasicDataSource.class); + }); } @Test public void testDataSourceIsInitializedEarly() { - load(TestInitializedDataSourceConfiguration.class, - "spring.datasource.initialize=true"); - assertThat(this.context.getBean( - TestInitializedDataSourceConfiguration.class).called).isTrue(); + this.contextLoader.config(TestInitializedDataSourceConfiguration.class) + .env("spring.datasource.initialize=true").load(context -> + assertThat(context.getBean( + TestInitializedDataSourceConfiguration.class).called).isTrue()); } - @SuppressWarnings("unchecked") - private T autoConfigureDataSource(Class expectedType, - final String... hiddenPackages) { - load(null, new HidePackagesClassLoader(hiddenPackages)); - DataSource bean = this.context.getBean(DataSource.class); - assertThat(bean).isInstanceOf(expectedType); - return (T) bean; - } - - public void load(String... environment) { - load(null, environment); - } - - public void load(Class config, String... environment) { - load(config, null, environment); - } - - public void load(Class config, ClassLoader classLoader, String... environment) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - if (classLoader != null) { - ctx.setClassLoader(classLoader); - } - TestPropertyValues - .of("spring.datasource.initialize=false", - "spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()) - .applyTo(ctx); - TestPropertyValues.of(environment).applyTo(ctx); - if (config != null) { - ctx.register(config); - } - ctx.register(DataSourceAutoConfiguration.class); - ctx.refresh(); - this.context = ctx; + private void assertDataSource(Class expectedType, + List hiddenPackages, Consumer consumer) { + HidePackagesClassLoader classLoader = new HidePackagesClassLoader( + hiddenPackages.toArray(new String[hiddenPackages.size()])); + this.contextLoader + .classLoader(classLoader) + .load(context -> { + DataSource bean = context.getBean(DataSource.class); + assertThat(bean).isInstanceOf(expectedType); + consumer.accept(expectedType.cast(bean)); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilderTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilderTests.java index 7e29f081a3..f80d8f6dd2 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilderTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilderTests.java @@ -26,6 +26,8 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.junit.After; import org.junit.Test; +import org.springframework.boot.test.context.HidePackagesClassLoader; + import static org.assertj.core.api.Assertions.assertThat; /** diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java index a09754893e..08ead25cbf 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfigurationTests.java @@ -21,15 +21,13 @@ import javax.jms.Session; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.pool.PooledConnectionFactory; -import org.junit.After; import org.junit.Test; import org.springframework.beans.BeansException; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -63,351 +61,352 @@ public class JmsAutoConfigurationTests { private static final String ACTIVEMQ_NETWORK_URL = "tcp://localhost:61616"; - private AnnotationConfigApplicationContext context; - - @After - public void close() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader().autoConfig( + ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class); @Test public void testDefaultJmsConfiguration() { - load(TestConfiguration.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - JmsMessagingTemplate messagingTemplate = this.context - .getBean(JmsMessagingTemplate.class); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); - assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); - assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) - .getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); - assertThat(this.context.containsBean("jmsListenerContainerFactory")).isTrue(); + this.contextLoader.config(TestConfiguration.class).load(context -> { + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + JmsMessagingTemplate messagingTemplate = context + .getBean(JmsMessagingTemplate.class); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); + assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) + .getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); + assertThat(context.containsBean("jmsListenerContainerFactory")).isTrue(); + }); } @Test public void testConnectionFactoryBackOff() { - load(TestConfiguration2.class); - assertThat(this.context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) - .isEqualTo("foobar"); + this.contextLoader.config(TestConfiguration2.class).load(context -> + assertThat(context.getBean(ActiveMQConnectionFactory.class) + .getBrokerURL()).isEqualTo("foobar")); } @Test public void testJmsTemplateBackOff() { - load(TestConfiguration3.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.getPriority()).isEqualTo(999); + this.contextLoader.config(TestConfiguration3.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getPriority()).isEqualTo(999); + }); } @Test public void testJmsMessagingTemplateBackOff() { - load(TestConfiguration5.class); - JmsMessagingTemplate messagingTemplate = this.context - .getBean(JmsMessagingTemplate.class); - assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); + this.contextLoader.config(TestConfiguration5.class).load(context -> { + JmsMessagingTemplate messagingTemplate = context + .getBean(JmsMessagingTemplate.class); + assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); + }); } @Test public void testJmsTemplateBackOffEverything() { - this.context = createContext(TestConfiguration2.class, TestConfiguration3.class, - TestConfiguration5.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.getPriority()).isEqualTo(999); - assertThat(this.context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) - .isEqualTo("foobar"); - JmsMessagingTemplate messagingTemplate = this.context - .getBean(JmsMessagingTemplate.class); - assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); - assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); + this.contextLoader.config(TestConfiguration2.class, TestConfiguration3.class, + TestConfiguration5.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getPriority()).isEqualTo(999); + assertThat(context.getBean(ActiveMQConnectionFactory.class).getBrokerURL()) + .isEqualTo("foobar"); + JmsMessagingTemplate messagingTemplate = context + .getBean(JmsMessagingTemplate.class); + assertThat(messagingTemplate.getDefaultDestinationName()).isEqualTo("fooBar"); + assertThat(messagingTemplate.getJmsTemplate()).isEqualTo(jmsTemplate); + }); } @Test public void testEnableJmsCreateDefaultContainerFactory() { - load(EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); + this.contextLoader.config(EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + }); } @Test public void testJmsListenerContainerFactoryBackOff() { - this.context = createContext(TestConfiguration6.class, - EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(SimpleJmsListenerContainerFactory.class); + this.contextLoader.config(TestConfiguration6.class, + EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(SimpleJmsListenerContainerFactory.class); + }); } @Test public void testJmsListenerContainerFactoryWithCustomSettings() { - load(EnableJmsConfiguration.class, "spring.jms.listener.autoStartup=false", - "spring.jms.listener.acknowledgeMode=client", - "spring.jms.listener.concurrency=2", - "spring.jms.listener.maxConcurrency=10"); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.isAutoStartup()).isFalse(); - assertThat(listenerContainer.getSessionAcknowledgeMode()) - .isEqualTo(Session.CLIENT_ACKNOWLEDGE); - assertThat(listenerContainer.getConcurrentConsumers()).isEqualTo(2); - assertThat(listenerContainer.getMaxConcurrentConsumers()).isEqualTo(10); + this.contextLoader.config(EnableJmsConfiguration.class) + .env("spring.jms.listener.autoStartup=false", + "spring.jms.listener.acknowledgeMode=client", + "spring.jms.listener.concurrency=2", + "spring.jms.listener.maxConcurrency=10").load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.isAutoStartup()).isFalse(); + assertThat(listenerContainer.getSessionAcknowledgeMode()) + .isEqualTo(Session.CLIENT_ACKNOWLEDGE); + assertThat(listenerContainer.getConcurrentConsumers()).isEqualTo(2); + assertThat(listenerContainer.getMaxConcurrentConsumers()).isEqualTo(10); + }); } @Test public void testDefaultContainerFactoryWithJtaTransactionManager() { - this.context = createContext(TestConfiguration7.class, - EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.isSessionTransacted()).isFalse(); - assertThat(new DirectFieldAccessor(listenerContainer) - .getPropertyValue("transactionManager")) - .isSameAs(this.context.getBean(JtaTransactionManager.class)); + this.contextLoader.config(TestConfiguration7.class, + EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.isSessionTransacted()).isFalse(); + assertThat(new DirectFieldAccessor(listenerContainer) + .getPropertyValue("transactionManager")) + .isSameAs(context.getBean(JtaTransactionManager.class)); + }); } @Test public void testDefaultContainerFactoryNonJtaTransactionManager() { - this.context = createContext(TestConfiguration8.class, - EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.isSessionTransacted()).isTrue(); - assertThat(new DirectFieldAccessor(listenerContainer) - .getPropertyValue("transactionManager")).isNull(); + this.contextLoader.config(TestConfiguration8.class, + EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.isSessionTransacted()).isTrue(); + assertThat(new DirectFieldAccessor(listenerContainer) + .getPropertyValue("transactionManager")).isNull(); + }); } @Test public void testDefaultContainerFactoryNoTransactionManager() { - this.context = createContext(EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.isSessionTransacted()).isTrue(); - assertThat(new DirectFieldAccessor(listenerContainer) - .getPropertyValue("transactionManager")).isNull(); + this.contextLoader.config(EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.isSessionTransacted()).isTrue(); + assertThat(new DirectFieldAccessor(listenerContainer) + .getPropertyValue("transactionManager")).isNull(); + }); } @Test public void testDefaultContainerFactoryWithMessageConverters() { - this.context = createContext(MessageConvertersConfiguration.class, - EnableJmsConfiguration.class); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "jmsListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory.getClass()) - .isEqualTo(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.getMessageConverter()) - .isSameAs(this.context.getBean("myMessageConverter")); + this.contextLoader.config(MessageConvertersConfiguration.class, + EnableJmsConfiguration.class).load(context -> { + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "jmsListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory.getClass()) + .isEqualTo(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.getMessageConverter()) + .isSameAs(context.getBean("myMessageConverter")); + }); } @Test public void testCustomContainerFactoryWithConfigurer() { - this.context = doLoad( - new Class[] { TestConfiguration9.class, EnableJmsConfiguration.class }, - "spring.jms.listener.autoStartup=false"); - assertThat(this.context.containsBean("jmsListenerContainerFactory")).isTrue(); - JmsListenerContainerFactory jmsListenerContainerFactory = this.context.getBean( - "customListenerContainerFactory", JmsListenerContainerFactory.class); - assertThat(jmsListenerContainerFactory) - .isInstanceOf(DefaultJmsListenerContainerFactory.class); - DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(listenerContainer.getCacheLevel()) - .isEqualTo(DefaultMessageListenerContainer.CACHE_CONSUMER); - assertThat(listenerContainer.isAutoStartup()).isFalse(); + this.contextLoader.config(TestConfiguration9.class, EnableJmsConfiguration.class) + .env("spring.jms.listener.autoStartup=false").load(context -> { + assertThat(context.containsBean("jmsListenerContainerFactory")).isTrue(); + JmsListenerContainerFactory jmsListenerContainerFactory = context.getBean( + "customListenerContainerFactory", JmsListenerContainerFactory.class); + assertThat(jmsListenerContainerFactory) + .isInstanceOf(DefaultJmsListenerContainerFactory.class); + DefaultMessageListenerContainer listenerContainer = ((DefaultJmsListenerContainerFactory) jmsListenerContainerFactory) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(listenerContainer.getCacheLevel()) + .isEqualTo(DefaultMessageListenerContainer.CACHE_CONSUMER); + assertThat(listenerContainer.isAutoStartup()).isFalse(); + }); } @Test public void testJmsTemplateWithMessageConverter() { - load(MessageConvertersConfiguration.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.getMessageConverter()) - .isSameAs(this.context.getBean("myMessageConverter")); + this.contextLoader.config(MessageConvertersConfiguration.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getMessageConverter()) + .isSameAs(context.getBean("myMessageConverter")); + }); } @Test public void testJmsTemplateWithDestinationResolver() { - load(DestinationResolversConfiguration.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.getDestinationResolver()) - .isSameAs(this.context.getBean("myDestinationResolver")); + this.contextLoader.config(DestinationResolversConfiguration.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getDestinationResolver()) + .isSameAs(context.getBean("myDestinationResolver")); + }); } @Test public void testJmsTemplateFullCustomization() { - load(MessageConvertersConfiguration.class, + this.contextLoader.config(MessageConvertersConfiguration.class).env( "spring.jms.template.default-destination=testQueue", "spring.jms.template.delivery-delay=500", "spring.jms.template.delivery-mode=non-persistent", "spring.jms.template.priority=6", "spring.jms.template.time-to-live=6000", - "spring.jms.template.receive-timeout=2000"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.getMessageConverter()) - .isSameAs(this.context.getBean("myMessageConverter")); - assertThat(jmsTemplate.isPubSubDomain()).isFalse(); - assertThat(jmsTemplate.getDefaultDestinationName()).isEqualTo("testQueue"); - assertThat(jmsTemplate.getDeliveryDelay()).isEqualTo(500); - assertThat(jmsTemplate.getDeliveryMode()).isEqualTo(1); - assertThat(jmsTemplate.getPriority()).isEqualTo(6); - assertThat(jmsTemplate.getTimeToLive()).isEqualTo(6000); - assertThat(jmsTemplate.isExplicitQosEnabled()).isTrue(); - assertThat(jmsTemplate.getReceiveTimeout()).isEqualTo(2000); + "spring.jms.template.receive-timeout=2000").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.getMessageConverter()) + .isSameAs(context.getBean("myMessageConverter")); + assertThat(jmsTemplate.isPubSubDomain()).isFalse(); + assertThat(jmsTemplate.getDefaultDestinationName()).isEqualTo("testQueue"); + assertThat(jmsTemplate.getDeliveryDelay()).isEqualTo(500); + assertThat(jmsTemplate.getDeliveryMode()).isEqualTo(1); + assertThat(jmsTemplate.getPriority()).isEqualTo(6); + assertThat(jmsTemplate.getTimeToLive()).isEqualTo(6000); + assertThat(jmsTemplate.isExplicitQosEnabled()).isTrue(); + assertThat(jmsTemplate.getReceiveTimeout()).isEqualTo(2000); + }); } @Test public void testPubSubDisabledByDefault() { - load(TestConfiguration.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.isPubSubDomain()).isFalse(); + this.contextLoader.config(TestConfiguration.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.isPubSubDomain()).isFalse(); + }); } @Test public void testJmsTemplatePostProcessedSoThatPubSubIsTrue() { - load(TestConfiguration4.class); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - assertThat(jmsTemplate.isPubSubDomain()).isTrue(); + this.contextLoader.config(TestConfiguration4.class).load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + assertThat(jmsTemplate.isPubSubDomain()).isTrue(); + }); } @Test public void testPubSubDomainActive() { - load(TestConfiguration.class, "spring.jms.pubSubDomain:true"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - DefaultMessageListenerContainer defaultMessageListenerContainer = this.context - .getBean(DefaultJmsListenerContainerFactory.class) - .createListenerContainer(mock(JmsListenerEndpoint.class)); - assertThat(jmsTemplate.isPubSubDomain()).isTrue(); - assertThat(defaultMessageListenerContainer.isPubSubDomain()).isTrue(); + this.contextLoader.config(TestConfiguration.class) + .env("spring.jms.pubSubDomain:true").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + DefaultMessageListenerContainer defaultMessageListenerContainer = context + .getBean(DefaultJmsListenerContainerFactory.class) + .createListenerContainer(mock(JmsListenerEndpoint.class)); + assertThat(jmsTemplate.isPubSubDomain()).isTrue(); + assertThat(defaultMessageListenerContainer.isPubSubDomain()).isTrue(); + }); } @Test public void testPubSubDomainOverride() { - load(TestConfiguration.class, "spring.jms.pubSubDomain:false"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(jmsTemplate.isPubSubDomain()).isFalse(); - assertThat(connectionFactory).isNotNull(); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + this.contextLoader.config(TestConfiguration.class) + .env("spring.jms.pubSubDomain:false").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(jmsTemplate.isPubSubDomain()).isFalse(); + assertThat(connectionFactory).isNotNull(); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + }); } @Test public void testActiveMQOverriddenStandalone() { - load(TestConfiguration.class, "spring.activemq.inMemory:false"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(connectionFactory).isNotNull(); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); - assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) - .getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); + this.contextLoader.config(TestConfiguration.class) + .env("spring.activemq.inMemory:false").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(connectionFactory).isNotNull(); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) + .getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); + }); } @Test public void testActiveMQOverriddenRemoteHost() { - load(TestConfiguration.class, - "spring.activemq.brokerUrl:tcp://remote-host:10000"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(connectionFactory).isNotNull(); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); - assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) - .getBrokerURL()).isEqualTo("tcp://remote-host:10000"); + this.contextLoader.config(TestConfiguration.class) + .env("spring.activemq.brokerUrl:tcp://remote-host:10000").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(connectionFactory).isNotNull(); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + assertThat(((ActiveMQConnectionFactory) jmsTemplate.getConnectionFactory()) + .getBrokerURL()).isEqualTo("tcp://remote-host:10000"); + }); } @Test public void testActiveMQOverriddenPool() { - load(TestConfiguration.class, "spring.activemq.pool.enabled:true"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - PooledConnectionFactory pool = this.context - .getBean(PooledConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(pool).isNotNull(); - assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); - ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool - .getConnectionFactory(); - assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); + this.contextLoader.config(TestConfiguration.class) + .env("spring.activemq.pool.enabled:true").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + PooledConnectionFactory pool = context.getBean(PooledConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(pool).isNotNull(); + assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); + ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool + .getConnectionFactory(); + assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_EMBEDDED_URL); + }); } @Test public void testActiveMQOverriddenPoolAndStandalone() { - load(TestConfiguration.class, "spring.activemq.pool.enabled:true", - "spring.activemq.inMemory:false"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - PooledConnectionFactory pool = this.context - .getBean(PooledConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(pool).isNotNull(); - assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); - ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool - .getConnectionFactory(); - assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); + this.contextLoader.config(TestConfiguration.class) + .env("spring.activemq.pool.enabled:true", + "spring.activemq.inMemory:false").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + PooledConnectionFactory pool = context.getBean(PooledConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(pool).isNotNull(); + assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); + ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool + .getConnectionFactory(); + assertThat(factory.getBrokerURL()).isEqualTo(ACTIVEMQ_NETWORK_URL); + }); } @Test public void testActiveMQOverriddenPoolAndRemoteServer() { - load(TestConfiguration.class, "spring.activemq.pool.enabled:true", - "spring.activemq.brokerUrl:tcp://remote-host:10000"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - PooledConnectionFactory pool = this.context - .getBean(PooledConnectionFactory.class); - assertThat(jmsTemplate).isNotNull(); - assertThat(pool).isNotNull(); - assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); - ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool - .getConnectionFactory(); - assertThat(factory.getBrokerURL()).isEqualTo("tcp://remote-host:10000"); + this.contextLoader.config(TestConfiguration.class).env( + "spring.activemq.pool.enabled:true", + "spring.activemq.brokerUrl:tcp://remote-host:10000").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + PooledConnectionFactory pool = context.getBean(PooledConnectionFactory.class); + assertThat(jmsTemplate).isNotNull(); + assertThat(pool).isNotNull(); + assertThat(pool).isEqualTo(jmsTemplate.getConnectionFactory()); + ActiveMQConnectionFactory factory = (ActiveMQConnectionFactory) pool + .getConnectionFactory(); + assertThat(factory.getBrokerURL()).isEqualTo("tcp://remote-host:10000"); + }); } @Test public void enableJmsAutomatically() throws Exception { - load(NoEnableJmsConfiguration.class); - AnnotationConfigApplicationContext ctx = this.context; - ctx.getBean(JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME); - ctx.getBean(JmsListenerConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME); - } - - private AnnotationConfigApplicationContext createContext( - Class... additionalClasses) { - return doLoad(additionalClasses); - } - - private void load(Class config, String... environment) { - this.context = doLoad(new Class[] { config }, environment); - } - - private AnnotationConfigApplicationContext doLoad(Class[] configs, - String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - applicationContext.register(configs); - applicationContext.register(ActiveMQAutoConfiguration.class, - JmsAutoConfiguration.class); - TestPropertyValues.of(environment).applyTo(applicationContext); - applicationContext.refresh(); - return applicationContext; + this.contextLoader.config(NoEnableJmsConfiguration.class).load(context -> { + context.getBean(JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME); + context.getBean(JmsListenerConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME); + }); } @Configuration diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java index f1d4449bdd..64e177c29e 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQAutoConfigurationTests.java @@ -24,8 +24,7 @@ import org.apache.activemq.pool.PooledConnectionFactory; import org.junit.Test; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -42,70 +41,59 @@ import static org.mockito.Mockito.mockingDetails; */ public class ActiveMQAutoConfigurationTests { - private AnnotationConfigApplicationContext context; + private final ContextLoader contextLoader = new ContextLoader().autoConfig( + ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class); @Test public void brokerIsEmbeddedByDefault() { - load(EmptyConfiguration.class); - ConnectionFactory connectionFactory = this.context - .getBean(ConnectionFactory.class); - assertThat(connectionFactory).isInstanceOf(ActiveMQConnectionFactory.class); - String brokerUrl = ((ActiveMQConnectionFactory) connectionFactory).getBrokerURL(); - assertThat(brokerUrl).isEqualTo("vm://localhost?broker.persistent=false"); + this.contextLoader.config(EmptyConfiguration.class).load(context -> { + ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); + assertThat(connectionFactory).isInstanceOf(ActiveMQConnectionFactory.class); + String brokerUrl = ((ActiveMQConnectionFactory) connectionFactory).getBrokerURL(); + assertThat(brokerUrl).isEqualTo("vm://localhost?broker.persistent=false"); + }); } @Test public void configurationBacksOffWhenCustomConnectionFactoryExists() { - load(CustomConnectionFactoryConfiguration.class); - assertThat(mockingDetails(this.context.getBean(ConnectionFactory.class)).isMock()) - .isTrue(); + this.contextLoader.config(CustomConnectionFactoryConfiguration.class).load( + context -> assertThat(mockingDetails(context + .getBean(ConnectionFactory.class)).isMock()).isTrue()); } @Test public void customPooledConnectionFactoryConfiguration() { - load(EmptyConfiguration.class, "spring.activemq.pool.enabled:true", + this.contextLoader.config(EmptyConfiguration.class).env( + "spring.activemq.pool.enabled:true", "spring.activemq.pool.maxConnections:256", "spring.activemq.pool.idleTimeout:512", "spring.activemq.pool.expiryTimeout:4096", "spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024", - "spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048"); - ConnectionFactory connectionFactory = this.context - .getBean(ConnectionFactory.class); - assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); - PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory; - assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256); - assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512); - assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection()) - .isEqualTo(1024); - assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis()) - .isEqualTo(2048); - assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096); + "spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048").load(context -> { + ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); + assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); + PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory; + assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256); + assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512); + assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection()) + .isEqualTo(1024); + assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis()) + .isEqualTo(2048); + assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096); + }); } @Test public void pooledConnectionFactoryConfiguration() throws JMSException { - load(EmptyConfiguration.class, "spring.activemq.pool.enabled:true"); - ConnectionFactory connectionFactory = this.context - .getBean(ConnectionFactory.class); - assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); - this.context.close(); - assertThat(connectionFactory.createConnection()).isNull(); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.activemq.pool.enabled:true").load(context -> { + ConnectionFactory connectionFactory = context.getBean(ConnectionFactory.class); + assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); + context.close(); + assertThat(connectionFactory.createConnection()).isNull(); + }); } - private void load(Class config, String... environment) { - this.context = doLoad(config, environment); - } - - private AnnotationConfigApplicationContext doLoad(Class config, - String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - applicationContext.register(config); - applicationContext.register(ActiveMQAutoConfiguration.class, - JmsAutoConfiguration.class); - TestPropertyValues.of(environment).applyTo(applicationContext); - applicationContext.refresh(); - return applicationContext; - } @Configuration static class EmptyConfiguration { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java index 3c9eb65096..4f5afde4d1 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisAutoConfigurationTests.java @@ -37,15 +37,13 @@ import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl; import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl; import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl; import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; -import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.boot.test.context.ContextLoader; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.core.JmsTemplate; @@ -67,204 +65,221 @@ public class ArtemisAutoConfigurationTests { @Rule public final TemporaryFolder folder = new TemporaryFolder(); - private AnnotationConfigApplicationContext context; - - @After - public void tearDown() { - if (this.context != null) { - this.context.close(); - } - } + private final ContextLoader contextLoader = new ContextLoader().autoConfig( + ArtemisAutoConfiguration.class, JmsAutoConfiguration.class); @Test public void nativeConnectionFactory() { - load(EmptyConfiguration.class, "spring.artemis.mode:native"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); - assertNettyConnectionFactory(connectionFactory, "localhost", 61616); - assertThat(connectionFactory.getUser()).isNull(); - assertThat(connectionFactory.getPassword()).isNull(); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.mode:native").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + assertNettyConnectionFactory(connectionFactory, "localhost", 61616); + assertThat(connectionFactory.getUser()).isNull(); + assertThat(connectionFactory.getPassword()).isNull(); + }); } @Test public void nativeConnectionFactoryCustomHost() { - load(EmptyConfiguration.class, "spring.artemis.mode:native", - "spring.artemis.host:192.168.1.144", "spring.artemis.port:9876"); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertNettyConnectionFactory(connectionFactory, "192.168.1.144", 9876); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.mode:native", "spring.artemis.host:192.168.1.144", + "spring.artemis.port:9876").load(context -> { + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertNettyConnectionFactory(connectionFactory, "192.168.1.144", 9876); + }); } @Test public void nativeConnectionFactoryCredentials() { - load(EmptyConfiguration.class, "spring.artemis.mode:native", - "spring.artemis.user:user", "spring.artemis.password:secret"); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); - assertNettyConnectionFactory(connectionFactory, "localhost", 61616); - assertThat(connectionFactory.getUser()).isEqualTo("user"); - assertThat(connectionFactory.getPassword()).isEqualTo("secret"); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.mode:native", "spring.artemis.user:user", + "spring.artemis.password:secret").load(context -> { + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertThat(connectionFactory).isEqualTo(jmsTemplate.getConnectionFactory()); + assertNettyConnectionFactory(connectionFactory, "localhost", 61616); + assertThat(connectionFactory.getUser()).isEqualTo("user"); + assertThat(connectionFactory.getPassword()).isEqualTo("secret"); + }); } @Test public void embeddedConnectionFactory() { - load(EmptyConfiguration.class, "spring.artemis.mode:embedded"); - ArtemisProperties properties = this.context.getBean(ArtemisProperties.class); - assertThat(properties.getMode()).isEqualTo(ArtemisMode.EMBEDDED); - assertThat(this.context.getBeansOfType(EmbeddedJMS.class)).hasSize(1); - org.apache.activemq.artemis.core.config.Configuration configuration = this.context - .getBean(org.apache.activemq.artemis.core.config.Configuration.class); - assertThat(configuration.isPersistenceEnabled()).isFalse(); - assertThat(configuration.isSecurityEnabled()).isFalse(); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertInVmConnectionFactory(connectionFactory); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.mode:embedded").load(context -> { + ArtemisProperties properties = context.getBean(ArtemisProperties.class); + assertThat(properties.getMode()).isEqualTo(ArtemisMode.EMBEDDED); + assertThat(context.getBeansOfType(EmbeddedJMS.class)).hasSize(1); + org.apache.activemq.artemis.core.config.Configuration configuration = context + .getBean(org.apache.activemq.artemis.core.config.Configuration.class); + assertThat(configuration.isPersistenceEnabled()).isFalse(); + assertThat(configuration.isSecurityEnabled()).isFalse(); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertInVmConnectionFactory(connectionFactory); + }); } @Test public void embeddedConnectionFactoryByDefault() { // No mode is specified - load(EmptyConfiguration.class); - assertThat(this.context.getBeansOfType(EmbeddedJMS.class)).hasSize(1); - org.apache.activemq.artemis.core.config.Configuration configuration = this.context - .getBean(org.apache.activemq.artemis.core.config.Configuration.class); - assertThat(configuration.isPersistenceEnabled()).isFalse(); - assertThat(configuration.isSecurityEnabled()).isFalse(); + this.contextLoader.config(EmptyConfiguration.class).load(context -> { + assertThat(context.getBeansOfType(EmbeddedJMS.class)).hasSize(1); + org.apache.activemq.artemis.core.config.Configuration configuration = context + .getBean(org.apache.activemq.artemis.core.config.Configuration.class); + assertThat(configuration.isPersistenceEnabled()).isFalse(); + assertThat(configuration.isSecurityEnabled()).isFalse(); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertInVmConnectionFactory(connectionFactory); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertInVmConnectionFactory(connectionFactory); + }); } @Test public void nativeConnectionFactoryIfEmbeddedServiceDisabledExplicitly() { // No mode is specified - load(EmptyConfiguration.class, "spring.artemis.embedded.enabled:false"); - assertThat(this.context.getBeansOfType(EmbeddedJMS.class)).isEmpty(); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertNettyConnectionFactory(connectionFactory, "localhost", 61616); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.embedded.enabled:false").load(context -> { + assertThat(context.getBeansOfType(EmbeddedJMS.class)).isEmpty(); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertNettyConnectionFactory(connectionFactory, "localhost", 61616); + }); } @Test public void embeddedConnectionFactoryEvenIfEmbeddedServiceDisabled() { // No mode is specified - load(EmptyConfiguration.class, "spring.artemis.mode:embedded", - "spring.artemis.embedded.enabled:false"); - assertThat(this.context.getBeansOfType(EmbeddedJMS.class)).isEmpty(); - ActiveMQConnectionFactory connectionFactory = this.context - .getBean(ActiveMQConnectionFactory.class); - assertInVmConnectionFactory(connectionFactory); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.mode:embedded", + "spring.artemis.embedded.enabled:false").load(context -> { + assertThat(context.getBeansOfType(EmbeddedJMS.class)).isEmpty(); + ActiveMQConnectionFactory connectionFactory = context + .getBean(ActiveMQConnectionFactory.class); + assertInVmConnectionFactory(connectionFactory); + }); } @Test public void embeddedServerWithDestinations() { - load(EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue1,Queue2", - "spring.artemis.embedded.topics=Topic1"); - DestinationChecker checker = new DestinationChecker(this.context); - checker.checkQueue("Queue1", true); - checker.checkQueue("Queue2", true); - checker.checkQueue("QueueWillNotBeAutoCreated", true); - checker.checkTopic("Topic1", true); - checker.checkTopic("TopicWillBeAutoCreated", true); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.embedded.queues=Queue1,Queue2", + "spring.artemis.embedded.topics=Topic1").load(context -> { + DestinationChecker checker = new DestinationChecker(context); + checker.checkQueue("Queue1", true); + checker.checkQueue("Queue2", true); + checker.checkQueue("QueueWillNotBeAutoCreated", true); + checker.checkTopic("Topic1", true); + checker.checkTopic("TopicWillBeAutoCreated", true); + }); } @Test public void embeddedServerWithDestinationConfig() { - load(DestinationConfiguration.class); - DestinationChecker checker = new DestinationChecker(this.context); - checker.checkQueue("sampleQueue", true); - checker.checkTopic("sampleTopic", true); + this.contextLoader.config(DestinationConfiguration.class).load(context -> { + DestinationChecker checker = new DestinationChecker(context); + checker.checkQueue("sampleQueue", true); + checker.checkTopic("sampleTopic", true); + }); } @Test public void embeddedServiceWithCustomJmsConfiguration() { // Ignored with custom config - load(CustomJmsConfiguration.class, - "spring.artemis.embedded.queues=Queue1,Queue2"); - DestinationChecker checker = new DestinationChecker(this.context); - checker.checkQueue("custom", true); // See CustomJmsConfiguration - checker.checkQueue("Queue1", true); - checker.checkQueue("Queue2", true); + this.contextLoader.config(CustomJmsConfiguration.class) + .env("spring.artemis.embedded.queues=Queue1,Queue2").load(context -> { + DestinationChecker checker = new DestinationChecker(context); + checker.checkQueue("custom", true); // See CustomJmsConfiguration + checker.checkQueue("Queue1", true); + checker.checkQueue("Queue2", true); + }); } @Test public void embeddedServiceWithCustomArtemisConfiguration() { - load(CustomArtemisConfiguration.class); - org.apache.activemq.artemis.core.config.Configuration configuration = this.context - .getBean(org.apache.activemq.artemis.core.config.Configuration.class); - assertThat(configuration.getName()).isEqualTo("customFooBar"); + this.contextLoader.config(CustomArtemisConfiguration.class).load(context -> { + org.apache.activemq.artemis.core.config.Configuration configuration = context + .getBean(org.apache.activemq.artemis.core.config.Configuration.class); + assertThat(configuration.getName()).isEqualTo("customFooBar"); + }); } @Test public void embeddedWithPersistentMode() throws IOException, JMSException { File dataFolder = this.folder.newFolder(); + final String msgId = UUID.randomUUID().toString(); // Start the server and post a message to some queue - load(EmptyConfiguration.class, "spring.artemis.embedded.queues=TestQueue", + this.contextLoader + .config(EmptyConfiguration.class).env( + "spring.artemis.embedded.queues=TestQueue", "spring.artemis.embedded.persistent:true", - "spring.artemis.embedded.dataDirectory:" + dataFolder.getAbsolutePath()); + "spring.artemis.embedded.dataDirectory:" + dataFolder.getAbsolutePath()) + .load(context -> { - final String msgId = UUID.randomUUID().toString(); - JmsTemplate jmsTemplate = this.context.getBean(JmsTemplate.class); - jmsTemplate.send("TestQueue", new MessageCreator() { - @Override - public Message createMessage(Session session) throws JMSException { - return session.createTextMessage(msgId); - } - }); - this.context.close(); // Shutdown the broker + JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); + jmsTemplate.send("TestQueue", new MessageCreator() { + @Override + public Message createMessage(Session session) throws JMSException { + return session.createTextMessage(msgId); + } + }); + }); // Start the server again and check if our message is still here - load(EmptyConfiguration.class, "spring.artemis.embedded.queues=TestQueue", - "spring.artemis.embedded.persistent:true", - "spring.artemis.embedded.dataDirectory:" + dataFolder.getAbsolutePath()); + this.contextLoader.load(context -> { - JmsTemplate jmsTemplate2 = this.context.getBean(JmsTemplate.class); - jmsTemplate2.setReceiveTimeout(1000L); - Message message = jmsTemplate2.receive("TestQueue"); - assertThat(message).isNotNull(); - assertThat(((TextMessage) message).getText()).isEqualTo(msgId); + JmsTemplate jmsTemplate2 = context.getBean(JmsTemplate.class); + jmsTemplate2.setReceiveTimeout(1000L); + Message message = jmsTemplate2.receive("TestQueue"); + assertThat(message).isNotNull(); + assertThat(((TextMessage) message).getText()).isEqualTo(msgId); + }); } @Test public void severalEmbeddedBrokers() { - load(EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue1"); - try (AnnotationConfigApplicationContext anotherContext = doLoad( - EmptyConfiguration.class, "spring.artemis.embedded.queues=Queue2")) { - ArtemisProperties properties = this.context.getBean(ArtemisProperties.class); - ArtemisProperties anotherProperties = anotherContext - .getBean(ArtemisProperties.class); - assertThat(properties.getEmbedded().getServerId() < anotherProperties - .getEmbedded().getServerId()).isTrue(); - DestinationChecker checker = new DestinationChecker(this.context); - checker.checkQueue("Queue1", true); - checker.checkQueue("Queue2", true); - DestinationChecker anotherChecker = new DestinationChecker(anotherContext); - anotherChecker.checkQueue("Queue2", true); - anotherChecker.checkQueue("Queue1", true); - } + this.contextLoader.config(EmptyConfiguration.class).env( + "spring.artemis.embedded.queues=Queue1").load(rootContext -> { + this.contextLoader.env("spring.artemis.embedded.queues=Queue2").load(anotherContext -> { + ArtemisProperties properties = rootContext.getBean(ArtemisProperties.class); + ArtemisProperties anotherProperties = anotherContext + .getBean(ArtemisProperties.class); + assertThat(properties.getEmbedded().getServerId() < anotherProperties + .getEmbedded().getServerId()).isTrue(); + DestinationChecker checker = new DestinationChecker(anotherContext); + checker.checkQueue("Queue1", true); + checker.checkQueue("Queue2", true); + DestinationChecker anotherChecker = new DestinationChecker(anotherContext); + anotherChecker.checkQueue("Queue2", true); + anotherChecker.checkQueue("Queue1", true); + }); + }); } @Test public void connectToASpecificEmbeddedBroker() { - load(EmptyConfiguration.class, "spring.artemis.embedded.serverId=93", - "spring.artemis.embedded.queues=Queue1"); + this.contextLoader.config(EmptyConfiguration.class) + .env("spring.artemis.embedded.serverId=93", + "spring.artemis.embedded.queues=Queue1").load(context -> { + this.contextLoader.config(EmptyConfiguration.class).env( + "spring.artemis.mode=embedded", + "spring.artemis.embedded.serverId=93", /* Connect to the "main" broker */ + "spring.artemis.embedded.enabled=false" /* do not start a specific one */) + .load(anotherContext -> { + DestinationChecker checker = new DestinationChecker(context); + checker.checkQueue("Queue1", true); - try (AnnotationConfigApplicationContext anotherContext = doLoad( - EmptyConfiguration.class, "spring.artemis.mode=embedded", - "spring.artemis.embedded.serverId=93", /* Connect to the "main" broker */ - "spring.artemis.embedded.enabled=false" /* do not start a specific one */)) { - DestinationChecker checker = new DestinationChecker(this.context); - checker.checkQueue("Queue1", true); - - DestinationChecker anotherChecker = new DestinationChecker(anotherContext); - anotherChecker.checkQueue("Queue1", true); - } + DestinationChecker anotherChecker = new DestinationChecker(anotherContext); + anotherChecker.checkQueue("Queue1", true); + }); + }); } private TransportConfiguration assertInVmConnectionFactory( @@ -295,21 +310,6 @@ public class ArtemisAutoConfigurationTests { return transportConfigurations[0]; } - private void load(Class config, String... environment) { - this.context = doLoad(config, environment); - } - - private AnnotationConfigApplicationContext doLoad(Class config, - String... environment) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); - applicationContext.register(config); - applicationContext.register(ArtemisAutoConfiguration.class, - JmsAutoConfiguration.class); - TestPropertyValues.of(environment).applyTo(applicationContext); - applicationContext.refresh(); - return applicationContext; - } - private final static class DestinationChecker { private final JmsTemplate jmsTemplate; diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextConsumer.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextConsumer.java new file mode 100644 index 0000000000..da3cec8e2d --- /dev/null +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextConsumer.java @@ -0,0 +1,41 @@ +/* + * 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 org.springframework.context.ConfigurableApplicationContext; + +/** + * Callback interface used in tests to process a running + * {@link ConfigurableApplicationContext} with the ability to throw a (checked) + * exception. + * + * @author Stephane Nicoll + * @author Andy Wilkinson + * @since 2.0.0 + */ +@FunctionalInterface +public interface ContextConsumer { + + /** + * Performs this operation on the supplied {@link ConfigurableApplicationContext + * ApplicationContext}. + * @param context the application context to consume + * @throws Throwable any exception that might occur in assertions + */ + void accept(ConfigurableApplicationContext context) throws Throwable; + +} diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java new file mode 100644 index 0000000000..d801ea9441 --- /dev/null +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ContextLoader.java @@ -0,0 +1,315 @@ +/* + * 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 org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Manage the lifecycle of an {@link ApplicationContext}. Such helper is best used as + * a field of a test class, describing the shared configuration required for the test: + * + *
+ * public class FooAutoConfigurationTests {
+ *
+ *     private final ContextLoader contextLoader = new ContextLoader()
+ *             .autoConfig(FooAutoConfiguration.class).env("spring.foo=bar");
+ *
+ * }
+ * + *

The initialization above makes sure to register {@code FooAutoConfiguration} for all + * tests and set the {@code spring.foo} property to {@code bar} unless specified + * otherwise. + * + *

Based on the configuration above, a specific test can simulate what would happen + * if the user customizes a property and/or provides its own configuration: + * + *

+ * public class FooAutoConfigurationTests {
+ *
+ *     @Test
+ *     public someTest() {
+ *         this.contextLoader.config(UserConfig.class).env("spring.foo=biz")
+ *                 .load(context -> {
+ *            			// assertions using the context
+ *         });
+ *     }
+ *
+ * }
+ * + *

The test above includes an extra {@code UserConfig} class that is guaranteed to + * be processed before any auto-configuration. Also, {@code spring.foo} + * has been overwritten to {@code biz}. The {@link #load(ContextConsumer) load} method + * takes a consumer that can use the context to assert its state. Upon completion, the + * context is automatically closed. + * + *

If a failure scenario has to be tested, {@link #loadAndFail(Consumer)} can be used + * instead: it expects the startup of the context to fail and call the {@link Consumer} + * with the exception for further assertions. + * + * @author Stephane Nicoll + * @author Andy Wilkinson + * @since 2.0.0 + */ +public class ContextLoader { + + private final Map systemProperties = new HashMap<>(); + + private final List env = new ArrayList<>(); + + private final Set> userConfigurations = new LinkedHashSet<>(); + + private final LinkedList> autoConfigurations = new LinkedList<>(); + + private ClassLoader classLoader; + + /** + * 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 + */ + public ContextLoader 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. Name-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 + */ + public ContextLoader 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 + */ + public ContextLoader 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 + */ + public ContextLoader autoConfig(Class... autoConfigurations) { + if (!ObjectUtils.isEmpty(autoConfigurations)) { + this.autoConfigurations.addAll(Arrays.asList(autoConfigurations)); + } + return this; + } + + /** + * Add the specified auto-configuration at the beginning so that it is + * applied before any other existing auto-configurations, but after any + * user configuration. + * @param autoConfiguration the auto-configuration to add + * @return this instance + */ + public ContextLoader autoConfigFirst(Class autoConfiguration) { + this.autoConfigurations.addFirst(autoConfiguration); + 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 + */ + public ContextLoader 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} + */ + public void load(ContextConsumer consumer) { + try (ApplicationContextLifecycleHandler handler = new ApplicationContextLifecycleHandler()) { + try { + ConfigurableApplicationContext 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 + */ + public void loadAndFail(Consumer 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 the expected type of the failure + */ + public void loadAndFail(Class exceptionType, + Consumer 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 ConfigurableApplicationContext createApplicationContext() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + if (this.classLoader != null) { + ctx.setClassLoader(this.classLoader); + } + if (!ObjectUtils.isEmpty(this.env)) { + TestPropertyValues.of(this.env.toArray(new String[this.env.size()])) + .applyTo(ctx); + } + if (!ObjectUtils.isEmpty(this.userConfigurations)) { + ctx.register(this.userConfigurations.toArray( + new Class[this.userConfigurations.size()])); + } + if (!ObjectUtils.isEmpty(this.autoConfigurations)) { + LinkedHashSet> linkedHashSet = + new LinkedHashSet(this.autoConfigurations); + ctx.register(linkedHashSet.toArray( + new Class[this.autoConfigurations.size()])); + } + return ctx; + } + + /** + * Handles the lifecycle of the {@link ApplicationContext}. + */ + private class ApplicationContextLifecycleHandler implements Closeable { + + private final Map customSystemProperties; + + private final Map previousSystemProperties = new HashMap<>(); + + private ConfigurableApplicationContext context; + + ApplicationContextLifecycleHandler() { + this.customSystemProperties = new HashMap<>( + ContextLoader.this.systemProperties); + } + + public ConfigurableApplicationContext load() { + setCustomSystemProperties(); + ConfigurableApplicationContext context = createApplicationContext(); + 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); + } + }); + } + + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/HidePackagesClassLoader.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/HidePackagesClassLoader.java similarity index 77% rename from spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/HidePackagesClassLoader.java rename to spring-boot-test/src/main/java/org/springframework/boot/test/context/HidePackagesClassLoader.java index 263b44d615..71d9966ee2 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/HidePackagesClassLoader.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/HidePackagesClassLoader.java @@ -14,22 +14,28 @@ * limitations under the License. */ -package org.springframework.boot.autoconfigure.jdbc; +package org.springframework.boot.test.context; import java.net.URL; import java.net.URLClassLoader; /** - * Test {@link URLClassLoader} that hides configurable packages. + * Test {@link URLClassLoader} that hides configurable packages. No class + * in one of those packages or sub-packages are visible. * * @author Andy Wilkinson * @author Stephane Nicoll + * @since 2.0.0 */ -final class HidePackagesClassLoader extends URLClassLoader { +public final class HidePackagesClassLoader extends URLClassLoader { private final String[] hiddenPackages; - HidePackagesClassLoader(String... hiddenPackages) { + /** + * Create a new instance with the packages to hide. + * @param hiddenPackages the packages to hide + */ + public HidePackagesClassLoader(String... hiddenPackages) { super(new URL[0], HidePackagesClassLoader.class.getClassLoader()); this.hiddenPackages = hiddenPackages; } diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/rule/ContextLoaderTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/rule/ContextLoaderTests.java new file mode 100644 index 0000000000..ab1b2b952a --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/rule/ContextLoaderTests.java @@ -0,0 +1,236 @@ +/* + * 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.rule; + +import java.util.UUID; + +import com.google.gson.Gson; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.boot.test.context.ContextLoader; +import org.springframework.boot.test.context.HidePackagesClassLoader; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.ClassUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +/** + * Tests for {@link ContextLoader}. + * + * @author Stephane Nicoll + */ +public class ContextLoaderTests { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + private final ContextLoader contextLoader = new ContextLoader(); + + @Test + public void systemPropertyIsSetAndRemoved() { + String key = "test." + UUID.randomUUID().toString(); + assertThat(System.getProperties().containsKey(key)).isFalse(); + this.contextLoader.systemProperty(key, "value").load(context -> { + assertThat(System.getProperties().containsKey(key)).isTrue(); + assertThat(System.getProperties().getProperty(key)).isEqualTo("value"); + }); + assertThat(System.getProperties().containsKey(key)).isFalse(); + } + + @Test + public void systemPropertyIsRemovedIfContextFailed() { + String key = "test." + UUID.randomUUID().toString(); + assertThat(System.getProperties().containsKey(key)).isFalse(); + this.contextLoader.systemProperty(key, "value") + .config(ConfigC.class).loadAndFail(e -> { + }); + assertThat(System.getProperties().containsKey(key)).isFalse(); + } + + @Test + public void systemPropertyIsRestoredToItsOriginalValue() { + String key = "test." + UUID.randomUUID().toString(); + System.setProperty(key, "value"); + try { + assertThat(System.getProperties().getProperty(key)).isEqualTo("value"); + this.contextLoader.systemProperty(key, "newValue").load(context -> { + assertThat(System.getProperties().getProperty(key)).isEqualTo("newValue"); + }); + assertThat(System.getProperties().getProperty(key)).isEqualTo("value"); + } + finally { + System.clearProperty(key); + } + } + + @Test + public void systemPropertyCanBeSetToNullValue() { + String key = "test." + UUID.randomUUID().toString(); + assertThat(System.getProperties().containsKey(key)).isFalse(); + this.contextLoader.systemProperty(key, "value") + .systemProperty(key, null).load(context -> { + assertThat(System.getProperties().containsKey(key)).isFalse(); + }); + } + + @Test + public void systemPropertyNeedNonNullKey() { + this.thrown.expect(IllegalArgumentException.class); + this.contextLoader.systemProperty(null, "value"); + } + + @Test + public void envIsAdditive() { + this.contextLoader.env("test.foo=1").env("test.bar=2").load(context -> { + ConfigurableEnvironment environment = context.getBean( + ConfigurableEnvironment.class); + assertThat(environment.getProperty("test.foo", Integer.class)).isEqualTo(1); + assertThat(environment.getProperty("test.bar", Integer.class)).isEqualTo(2); + }); + } + + @Test + public void envOverridesExistingKey() { + this.contextLoader.env("test.foo=1").env("test.foo=2").load(context -> + assertThat(context.getBean(ConfigurableEnvironment.class) + .getProperty("test.foo", Integer.class)).isEqualTo(2)); + } + + @Test + public void configurationIsProcessedInOrder() { + this.contextLoader.config(ConfigA.class, AutoConfigA.class).load(context -> + assertThat(context.getBean("a")).isEqualTo("autoconfig-a")); + } + + @Test + public void configurationIsProcessedBeforeAutoConfiguration() { + this.contextLoader.autoConfig(AutoConfigA.class) + .config(ConfigA.class).load(context -> + assertThat(context.getBean("a")).isEqualTo("autoconfig-a")); + } + + @Test + public void configurationIsAdditive() { + this.contextLoader.config(AutoConfigA.class) + .config(AutoConfigB.class).load(context -> { + assertThat(context.containsBean("a")).isTrue(); + assertThat(context.containsBean("b")).isTrue(); + }); + } + + @Test + public void autoConfigureFirstIsAppliedProperly() { + this.contextLoader.autoConfig(ConfigA.class) + .autoConfigFirst(AutoConfigA.class).load(context -> + assertThat(context.getBean("a")).isEqualTo("a")); + } + + @Test + public void autoConfigurationIsAdditive() { + this.contextLoader.autoConfig(AutoConfigA.class) + .autoConfig(AutoConfigB.class).load(context -> { + assertThat(context.containsBean("a")).isTrue(); + assertThat(context.containsBean("b")).isTrue(); + }); + } + + @Test + public void loadAndFailWithExpectedException() { + this.contextLoader.config(ConfigC.class) + .loadAndFail(BeanCreationException.class, ex -> + assertThat(ex.getMessage()).contains("Error creating bean with name 'c'")); + } + + @Test + public void loadAndFailWithWrongException() { + this.thrown.expect(AssertionError.class); + this.thrown.expectMessage("Wrong application context failure exception"); + this.contextLoader.config(ConfigC.class) + .loadAndFail(IllegalArgumentException.class, ex -> { + }); + } + + @Test + public void classLoaderIsUsed() { + this.contextLoader.classLoader(new HidePackagesClassLoader( + Gson.class.getPackage().getName())).load(context -> { + try { + ClassUtils.forName(Gson.class.getName(), context.getClassLoader()); + fail("Should have thrown a ClassNotFoundException"); + } + catch (ClassNotFoundException e) { + // expected + } + }); + } + + @Configuration + static class ConfigA { + + @Bean + public String a() { + return "a"; + } + + } + + @Configuration + static class ConfigB { + + @Bean + public Integer b() { + return 1; + } + + } + + @Configuration + static class AutoConfigA { + + @Bean + public String a() { + return "autoconfig-a"; + } + + } + + @Configuration + static class AutoConfigB { + + @Bean + public Integer b() { + return 42; + } + + } + + @Configuration + static class ConfigC { + + @Bean + public String c(Integer value) { + return String.valueOf(value); + } + } + +}