Disable DevTools' post-processors and auto-config when running tests

Closes gh-5307
This commit is contained in:
Madhura Bhave
2019-04-15 15:40:38 -07:00
parent b164b16c21
commit ac2b0093c7
14 changed files with 411 additions and 151 deletions

View File

@@ -20,6 +20,9 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import javax.sql.DataSource;
@@ -49,18 +52,18 @@ import static org.mockito.Mockito.verify;
public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
@Test
public void singleManuallyConfiguredDataSourceIsNotClosed() throws SQLException {
ConfigurableApplicationContext context = createContext(
SingleDataSourceConfiguration.class);
public void singleManuallyConfiguredDataSourceIsNotClosed() throws Exception {
ConfigurableApplicationContext context = getContext(
() -> createContext(SingleDataSourceConfiguration.class));
DataSource dataSource = context.getBean(DataSource.class);
Statement statement = configureDataSourceBehavior(dataSource);
verify(statement, never()).execute("SHUTDOWN");
}
@Test
public void multipleDataSourcesAreIgnored() throws SQLException {
ConfigurableApplicationContext context = createContext(
MultipleDataSourcesConfiguration.class);
public void multipleDataSourcesAreIgnored() throws Exception {
ConfigurableApplicationContext context = getContext(
() -> createContext(MultipleDataSourcesConfiguration.class));
Collection<DataSource> dataSources = context.getBeansOfType(DataSource.class)
.values();
for (DataSource dataSource : dataSources) {
@@ -90,6 +93,20 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
return statement;
}
protected ConfigurableApplicationContext getContext(
Supplier<ConfigurableApplicationContext> supplier) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ConfigurableApplicationContext> atomicReference = new AtomicReference<>();
Thread thread = new Thread(() -> {
ConfigurableApplicationContext context = supplier.get();
latch.countDown();
atomicReference.getAndSet(context);
});
thread.start();
thread.join();
return atomicReference.get();
}
protected final ConfigurableApplicationContext createContext(Class<?>... classes) {
return this.createContext(null, classes);
}

View File

@@ -17,7 +17,6 @@
package org.springframework.boot.devtools.autoconfigure;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
@@ -58,9 +57,9 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void autoConfiguredInMemoryDataSourceIsShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext(
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
public void autoConfiguredInMemoryDataSourceIsShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -68,9 +67,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void autoConfiguredExternalDataSourceIsNotShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext("org.postgresql.Driver",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
public void autoConfiguredExternalDataSourceIsNotShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.postgresql.Driver", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -78,10 +78,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void h2ServerIsNotShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext("org.h2.Driver",
"jdbc:h2:hsql://localhost", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class);
public void h2ServerIsNotShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.h2.Driver", "jdbc:h2:hsql://localhost",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -89,10 +89,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void inMemoryH2IsShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext("org.h2.Driver",
"jdbc:h2:mem:test", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class);
public void inMemoryH2IsShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.h2.Driver", "jdbc:h2:mem:test", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -100,10 +100,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void hsqlServerIsNotShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:hsql://localhost", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class);
public void hsqlServerIsNotShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.hsqldb.jdbcDriver", "jdbc:hsqldb:hsql://localhost",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -111,10 +111,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void inMemoryHsqlIsShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver",
"jdbc:hsqldb:mem:test", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class);
public void inMemoryHsqlIsShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:test",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -122,10 +122,10 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void derbyClientIsNotShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext(
public void derbyClientIsNotShutdown() throws Exception {
ConfigurableApplicationContext context = getContext(() -> createContext(
"org.apache.derby.jdbc.ClientDriver", "jdbc:derby://localhost",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
@@ -133,13 +133,14 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
}
@Test
public void inMemoryDerbyIsShutdown() throws SQLException {
ConfigurableApplicationContext context = createContext(
"org.apache.derby.jdbc.EmbeddedDriver", "jdbc:derby:memory:test",
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
public void inMemoryDerbyIsShutdown() throws Exception {
ConfigurableApplicationContext configurableApplicationContext = getContext(
() -> createContext("org.apache.derby.jdbc.EmbeddedDriver",
"jdbc:derby:memory:test", DataSourceAutoConfiguration.class,
DataSourceSpyConfiguration.class));
Statement statement = configureDataSourceBehavior(
context.getBean(DataSource.class));
context.close();
configurableApplicationContext.getBean(DataSource.class));
configurableApplicationContext.close();
verify(statement, times(1)).execute("SHUTDOWN");
}

View File

@@ -21,6 +21,9 @@ import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.apache.catalina.Container;
import org.apache.catalina.core.StandardWrapper;
@@ -84,28 +87,29 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void thymeleafCacheIsFalse() {
this.context = initializeAndRun(Config.class);
public void thymeleafCacheIsFalse() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
SpringResourceTemplateResolver resolver = this.context
.getBean(SpringResourceTemplateResolver.class);
assertThat(resolver.isCacheable()).isFalse();
}
@Test
public void defaultPropertyCanBeOverriddenFromCommandLine() {
this.context = initializeAndRun(Config.class, "--spring.thymeleaf.cache=true");
public void defaultPropertyCanBeOverriddenFromCommandLine() throws Exception {
this.context = getContext(
() -> initializeAndRun(Config.class, "--spring.thymeleaf.cache=true"));
SpringResourceTemplateResolver resolver = this.context
.getBean(SpringResourceTemplateResolver.class);
assertThat(resolver.isCacheable()).isTrue();
}
@Test
public void defaultPropertyCanBeOverriddenFromUserHomeProperties() {
public void defaultPropertyCanBeOverriddenFromUserHomeProperties() throws Exception {
String userHome = System.getProperty("user.home");
System.setProperty("user.home",
new File("src/test/resources/user-home").getAbsolutePath());
try {
this.context = initializeAndRun(Config.class);
this.context = getContext(() -> initializeAndRun(Config.class));
SpringResourceTemplateResolver resolver = this.context
.getBean(SpringResourceTemplateResolver.class);
assertThat(resolver.isCacheable()).isTrue();
@@ -116,22 +120,22 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void resourceCachePeriodIsZero() {
this.context = initializeAndRun(WebResourcesConfig.class);
public void resourceCachePeriodIsZero() throws Exception {
this.context = getContext(() -> initializeAndRun(WebResourcesConfig.class));
ResourceProperties properties = this.context.getBean(ResourceProperties.class);
assertThat(properties.getCache().getPeriod()).isEqualTo(Duration.ZERO);
}
@Test
public void liveReloadServer() {
this.context = initializeAndRun(Config.class);
public void liveReloadServer() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
assertThat(server.isStarted()).isTrue();
}
@Test
public void liveReloadTriggeredOnContextRefresh() {
this.context = initializeAndRun(ConfigWithMockLiveReload.class);
public void liveReloadTriggeredOnContextRefresh() throws Exception {
this.context = getContext(() -> initializeAndRun(ConfigWithMockLiveReload.class));
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
reset(server);
this.context.publishEvent(new ContextRefreshedEvent(this.context));
@@ -139,8 +143,8 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void liveReloadTriggeredOnClassPathChangeWithoutRestart() {
this.context = initializeAndRun(ConfigWithMockLiveReload.class);
public void liveReloadTriggeredOnClassPathChangeWithoutRestart() throws Exception {
this.context = getContext(() -> initializeAndRun(ConfigWithMockLiveReload.class));
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
reset(server);
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
@@ -150,8 +154,8 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void liveReloadNotTriggeredOnClassPathChangeWithRestart() {
this.context = initializeAndRun(ConfigWithMockLiveReload.class);
public void liveReloadNotTriggeredOnClassPathChangeWithRestart() throws Exception {
this.context = getContext(() -> initializeAndRun(ConfigWithMockLiveReload.class));
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
reset(server);
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
@@ -161,17 +165,17 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void liveReloadDisabled() {
public void liveReloadDisabled() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("spring.devtools.livereload.enabled", false);
this.context = initializeAndRun(Config.class, properties);
this.context = getContext(() -> initializeAndRun(Config.class, properties));
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(OptionalLiveReloadServer.class));
}
@Test
public void restartTriggeredOnClassPathChangeWithRestart() {
this.context = initializeAndRun(Config.class);
public void restartTriggeredOnClassPathChangeWithRestart() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
Collections.emptySet(), true);
this.context.publishEvent(event);
@@ -179,8 +183,8 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void restartNotTriggeredOnClassPathChangeWithRestart() {
this.context = initializeAndRun(Config.class);
public void restartNotTriggeredOnClassPathChangeWithRestart() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
Collections.emptySet(), false);
this.context.publishEvent(event);
@@ -188,27 +192,27 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void restartWatchingClassPath() {
this.context = initializeAndRun(Config.class);
public void restartWatchingClassPath() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
ClassPathFileSystemWatcher watcher = this.context
.getBean(ClassPathFileSystemWatcher.class);
assertThat(watcher).isNotNull();
}
@Test
public void restartDisabled() {
public void restartDisabled() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("spring.devtools.restart.enabled", false);
this.context = initializeAndRun(Config.class, properties);
this.context = getContext(() -> initializeAndRun(Config.class, properties));
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(ClassPathFileSystemWatcher.class));
}
@Test
public void restartWithTriggerFile() {
public void restartWithTriggerFile() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("spring.devtools.restart.trigger-file", "somefile.txt");
this.context = initializeAndRun(Config.class, properties);
this.context = getContext(() -> initializeAndRun(Config.class, properties));
ClassPathFileSystemWatcher classPathWatcher = this.context
.getBean(ClassPathFileSystemWatcher.class);
Object watcher = ReflectionTestUtils.getField(classPathWatcher,
@@ -218,11 +222,11 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void watchingAdditionalPaths() {
public void watchingAdditionalPaths() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("spring.devtools.restart.additional-paths",
"src/main/java,src/test/java");
this.context = initializeAndRun(Config.class, properties);
this.context = getContext(() -> initializeAndRun(Config.class, properties));
ClassPathFileSystemWatcher classPathWatcher = this.context
.getBean(ClassPathFileSystemWatcher.class);
Object watcher = ReflectionTestUtils.getField(classPathWatcher,
@@ -236,8 +240,8 @@ public class LocalDevToolsAutoConfigurationTests {
}
@Test
public void devToolsSwitchesJspServletToDevelopmentMode() {
this.context = initializeAndRun(Config.class);
public void devToolsSwitchesJspServletToDevelopmentMode() throws Exception {
this.context = getContext(() -> initializeAndRun(Config.class));
TomcatWebServer tomcatContainer = (TomcatWebServer) ((ServletWebServerApplicationContext) this.context)
.getWebServer();
Container context = tomcatContainer.getTomcat().getHost().findChildren()[0];
@@ -247,6 +251,20 @@ public class LocalDevToolsAutoConfigurationTests {
assertThat(options.getDevelopment()).isTrue();
}
private ConfigurableApplicationContext getContext(
Supplier<ConfigurableApplicationContext> supplier) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ConfigurableApplicationContext> atomicReference = new AtomicReference<>();
Thread thread = new Thread(() -> {
ConfigurableApplicationContext context = supplier.get();
latch.countDown();
atomicReference.getAndSet(context);
});
thread.start();
thread.join();
return atomicReference.get();
}
private ConfigurableApplicationContext initializeAndRun(Class<?> config,
String... args) {
return initializeAndRun(config, Collections.emptyMap(), args);

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2012-2019 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
*
* https://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.devtools.autoconfigure;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link OnEnabledDevtoolsCondition}.
*
* @author Madhura Bhave
*/
public class OnEnabledDevtoolsConditionTests {
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(TestConfiguration.class);
}
@Test
public void outcomeWhenDevtoolsShouldBeEnabledIsTrueShouldMatch() throws Exception {
Thread thread = new Thread(() -> {
OnEnabledDevtoolsConditionTests.this.context.refresh();
assertThat(OnEnabledDevtoolsConditionTests.this.context.containsBean("test"))
.isTrue();
});
thread.start();
thread.join();
}
@Test
public void outcomeWhenDevtoolsShouldBeEnabledIsFalseShouldNotMatch() {
OnEnabledDevtoolsConditionTests.this.context.refresh();
assertThat(OnEnabledDevtoolsConditionTests.this.context.containsBean("test"))
.isFalse();
}
@Configuration(proxyBeanMethods = false)
static class TestConfiguration {
@Bean
@Conditional(OnEnabledDevtoolsCondition.class)
public String test() {
return "hello";
}
}
}

View File

@@ -16,6 +16,10 @@
package org.springframework.boot.devtools.autoconfigure;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -81,15 +85,16 @@ public class RemoteDevToolsAutoConfigurationTests {
}
@Test
public void disabledIfRemoteSecretIsMissing() {
loadContext("a:b");
public void disabledIfRemoteSecretIsMissing() throws Exception {
this.context = getContext(() -> loadContext("a:b"));
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(DispatcherFilter.class));
}
@Test
public void ignoresUnmappedUrl() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI("/restart");
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
@@ -99,7 +104,8 @@ public class RemoteDevToolsAutoConfigurationTests {
@Test
public void ignoresIfMissingSecretFromRequest() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI(DEFAULT_CONTEXT_PATH + "/restart");
filter.doFilter(this.request, this.response, this.chain);
@@ -108,7 +114,8 @@ public class RemoteDevToolsAutoConfigurationTests {
@Test
public void ignoresInvalidSecretInRequest() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI(DEFAULT_CONTEXT_PATH + "/restart");
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "invalid");
@@ -118,7 +125,8 @@ public class RemoteDevToolsAutoConfigurationTests {
@Test
public void invokeRestartWithDefaultSetup() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI(DEFAULT_CONTEXT_PATH + "/restart");
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
@@ -128,8 +136,9 @@ public class RemoteDevToolsAutoConfigurationTests {
@Test
public void invokeRestartWithCustomServerContextPath() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret",
"server.servlet.context-path:/test");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret",
"server.servlet.context-path:/test"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI("/test" + DEFAULT_CONTEXT_PATH + "/restart");
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
@@ -138,16 +147,18 @@ public class RemoteDevToolsAutoConfigurationTests {
}
@Test
public void disableRestart() {
loadContext("spring.devtools.remote.secret:supersecret",
"spring.devtools.remote.restart.enabled:false");
public void disableRestart() throws Exception {
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret",
"spring.devtools.remote.restart.enabled:false"));
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean("remoteRestartHandlerMapper"));
}
@Test
public void devToolsHealthReturns200() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI(DEFAULT_CONTEXT_PATH);
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
@@ -158,8 +169,9 @@ public class RemoteDevToolsAutoConfigurationTests {
@Test
public void devToolsHealthWithCustomServerContextPathReturns200() throws Exception {
loadContext("spring.devtools.remote.secret:supersecret",
"server.servlet.context-path:/test");
this.context = getContext(
() -> loadContext("spring.devtools.remote.secret:supersecret",
"server.servlet.context-path:/test"));
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
this.request.setRequestURI("/test" + DEFAULT_CONTEXT_PATH);
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
@@ -168,17 +180,34 @@ public class RemoteDevToolsAutoConfigurationTests {
assertThat(this.response.getStatus()).isEqualTo(200);
}
private AnnotationConfigServletWebApplicationContext getContext(
Supplier<AnnotationConfigServletWebApplicationContext> supplier)
throws Exception {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<AnnotationConfigServletWebApplicationContext> atomicReference = new AtomicReference<>();
Thread thread = new Thread(() -> {
AnnotationConfigServletWebApplicationContext context = supplier.get();
latch.countDown();
atomicReference.getAndSet(context);
});
thread.start();
thread.join();
return atomicReference.get();
}
private void assertRestartInvoked(boolean value) {
assertThat(this.context.getBean(MockHttpRestartServer.class).invoked)
.isEqualTo(value);
}
private void loadContext(String... properties) {
this.context = new AnnotationConfigServletWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(Config.class, PropertyPlaceholderAutoConfiguration.class);
TestPropertyValues.of(properties).applyTo(this.context);
this.context.refresh();
private AnnotationConfigServletWebApplicationContext loadContext(
String... properties) {
AnnotationConfigServletWebApplicationContext context = new AnnotationConfigServletWebApplicationContext();
context.setServletContext(new MockServletContext());
context.register(Config.class, PropertyPlaceholderAutoConfiguration.class);
TestPropertyValues.of(properties).applyTo(context);
context.refresh();
return context;
}
@Configuration(proxyBeanMethods = false)

View File

@@ -18,6 +18,9 @@ package org.springframework.boot.devtools.env;
import java.net.URL;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.junit.After;
import org.junit.Before;
@@ -61,37 +64,40 @@ public class DevToolPropertiesIntegrationTests {
}
@Test
public void classPropertyConditionIsAffectedByDevToolProperties() {
public void classPropertyConditionIsAffectedByDevToolProperties() throws Exception {
SpringApplication application = new SpringApplication(
ClassConditionConfiguration.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run();
this.context = getContext(application::run);
this.context.getBean(ClassConditionConfiguration.class);
}
@Test
public void beanMethodPropertyConditionIsAffectedByDevToolProperties() {
public void beanMethodPropertyConditionIsAffectedByDevToolProperties()
throws Exception {
SpringApplication application = new SpringApplication(
BeanConditionConfiguration.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run();
this.context = getContext(application::run);
this.context.getBean(MyBean.class);
}
@Test
public void postProcessWhenRestarterDisabledAndRemoteSecretNotSetShouldNotAddPropertySource() {
public void postProcessWhenRestarterDisabledAndRemoteSecretNotSetShouldNotAddPropertySource()
throws Exception {
Restarter.clearInstance();
Restarter.disable();
SpringApplication application = new SpringApplication(
BeanConditionConfiguration.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run();
this.context = getContext(application::run);
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(MyBean.class));
}
@Test
public void postProcessWhenRestarterDisabledAndRemoteSecretSetShouldAddPropertySource() {
public void postProcessWhenRestarterDisabledAndRemoteSecretSetShouldAddPropertySource()
throws Exception {
Restarter.clearInstance();
Restarter.disable();
SpringApplication application = new SpringApplication(
@@ -99,21 +105,35 @@ public class DevToolPropertiesIntegrationTests {
application.setWebApplicationType(WebApplicationType.NONE);
application.setDefaultProperties(
Collections.singletonMap("spring.devtools.remote.secret", "donttell"));
this.context = application.run();
this.context = getContext(application::run);
this.context.getBean(MyBean.class);
}
@Test
public void postProcessEnablesIncludeStackTraceProperty() {
public void postProcessEnablesIncludeStackTraceProperty() throws Exception {
SpringApplication application = new SpringApplication(TestConfiguration.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run();
this.context = getContext(application::run);
ConfigurableEnvironment environment = this.context.getEnvironment();
String property = environment.getProperty("server.error.include-stacktrace");
assertThat(property)
.isEqualTo(ErrorProperties.IncludeStacktrace.ALWAYS.toString());
}
protected ConfigurableApplicationContext getContext(
Supplier<ConfigurableApplicationContext> supplier) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ConfigurableApplicationContext> atomicReference = new AtomicReference<>();
Thread thread = new Thread(() -> {
ConfigurableApplicationContext context = supplier.get();
latch.countDown();
atomicReference.getAndSet(context);
});
thread.start();
thread.join();
return atomicReference.get();
}
@Configuration(proxyBeanMethods = false)
static class TestConfiguration {

View File

@@ -21,6 +21,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import org.junit.Before;
import org.junit.Rule;
@@ -60,18 +61,28 @@ public class DevToolsHomePropertiesPostProcessorTests {
out.close();
ConfigurableEnvironment environment = new MockEnvironment();
MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor();
postProcessor.postProcessEnvironment(environment, null);
runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null));
assertThat(environment.getProperty("abc")).isEqualTo("def");
}
@Test
public void ignoresMissingHomeProperties() {
public void ignoresMissingHomeProperties() throws Exception {
ConfigurableEnvironment environment = new MockEnvironment();
MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor();
postProcessor.postProcessEnvironment(environment, null);
runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null));
assertThat(environment.getProperty("abc")).isNull();
}
protected void runPostProcessor(Runnable runnable) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Thread thread = new Thread(() -> {
runnable.run();
latch.countDown();
});
thread.start();
thread.join();
}
private class MockDevToolHomePropertiesPostProcessor
extends DevToolsHomePropertiesPostProcessor {