Disable DevTools' post-processors and auto-config when running tests
Closes gh-5307
This commit is contained in:
parent
b164b16c21
commit
ac2b0093c7
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility to deduce if Devtools should be enabled in the current context.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public final class DevtoolsEnablementDeducer {
|
||||
|
||||
private static final Set<String> SKIPPED_STACK_ELEMENTS;
|
||||
|
||||
static {
|
||||
Set<String> skipped = new LinkedHashSet<>();
|
||||
skipped.add("org.junit.runners.");
|
||||
skipped.add("org.junit.platform.");
|
||||
skipped.add("org.springframework.boot.test.");
|
||||
skipped.add("cucumber.runtime.");
|
||||
SKIPPED_STACK_ELEMENTS = Collections.unmodifiableSet(skipped);
|
||||
}
|
||||
|
||||
private DevtoolsEnablementDeducer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific {@link StackTraceElement} in the current thread's stacktrace
|
||||
* should cause devtools to be disabled.
|
||||
* @param thread the current thread
|
||||
* @return {@code true} if devtools should be enabled skipped
|
||||
*/
|
||||
public static boolean shouldEnable(Thread thread) {
|
||||
for (StackTraceElement element : thread.getStackTrace()) {
|
||||
if (isSkippedStackElement(element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isSkippedStackElement(StackTraceElement element) {
|
||||
for (String skipped : SKIPPED_STACK_ELEMENTS) {
|
||||
if (element.getClassName().startsWith(skipped)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -55,7 +55,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
|||
* @since 1.3.3
|
||||
*/
|
||||
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
@Conditional(DevToolsDataSourceCondition.class)
|
||||
@Conditional({ OnEnabledDevtoolsCondition.class, DevToolsDataSourceCondition.class })
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.springframework.boot.autoconfigure.condition.ConditionMessage;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.devtools.DevtoolsEnablementDeducer;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* A condition that checks if DevTools should be enabled.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class OnEnabledDevtoolsCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Devtools");
|
||||
boolean shouldEnable = DevtoolsEnablementDeducer
|
||||
.shouldEnable(Thread.currentThread());
|
||||
if (!shouldEnable) {
|
||||
return ConditionOutcome.noMatch(
|
||||
message.because("devtools is disabled for current context."));
|
||||
}
|
||||
return ConditionOutcome.match(message.because("devtools enabled."));
|
||||
}
|
||||
|
||||
}
|
|
@ -43,6 +43,7 @@ import org.springframework.boot.devtools.restart.server.HttpRestartServer;
|
|||
import org.springframework.boot.devtools.restart.server.HttpRestartServerHandler;
|
||||
import org.springframework.boot.devtools.restart.server.SourceFolderUrlFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
|
||||
|
@ -55,6 +56,7 @@ import org.springframework.http.server.ServerHttpRequest;
|
|||
* @since 1.3.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(OnEnabledDevtoolsCondition.class)
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.remote", name = "secret")
|
||||
@ConditionalOnClass({ Filter.class, ServerHttpRequest.class })
|
||||
@EnableConfigurationProperties({ ServerProperties.class, DevToolsProperties.class })
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.devtools.DevtoolsEnablementDeducer;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
|
@ -43,18 +44,20 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
|
|||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment,
|
||||
SpringApplication application) {
|
||||
File home = getHomeFolder();
|
||||
File propertyFile = (home != null) ? new File(home, FILE_NAME) : null;
|
||||
if (propertyFile != null && propertyFile.exists() && propertyFile.isFile()) {
|
||||
FileSystemResource resource = new FileSystemResource(propertyFile);
|
||||
Properties properties;
|
||||
try {
|
||||
properties = PropertiesLoaderUtils.loadProperties(resource);
|
||||
environment.getPropertySources().addFirst(
|
||||
new PropertiesPropertySource("devtools-local", properties));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to load " + FILE_NAME, ex);
|
||||
if (DevtoolsEnablementDeducer.shouldEnable(Thread.currentThread())) {
|
||||
File home = getHomeFolder();
|
||||
File propertyFile = (home != null) ? new File(home, FILE_NAME) : null;
|
||||
if (propertyFile != null && propertyFile.exists() && propertyFile.isFile()) {
|
||||
FileSystemResource resource = new FileSystemResource(propertyFile);
|
||||
Properties properties;
|
||||
try {
|
||||
properties = PropertiesLoaderUtils.loadProperties(resource);
|
||||
environment.getPropertySources().addFirst(
|
||||
new PropertiesPropertySource("devtools-local", properties));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to load " + FILE_NAME, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.devtools.DevtoolsEnablementDeducer;
|
||||
import org.springframework.boot.devtools.logger.DevToolsLogFactory;
|
||||
import org.springframework.boot.devtools.restart.Restarter;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
|
@ -79,7 +80,8 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
|
|||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment,
|
||||
SpringApplication application) {
|
||||
if (isLocalApplication(environment)) {
|
||||
if (DevtoolsEnablementDeducer.shouldEnable(Thread.currentThread())
|
||||
&& isLocalApplication(environment)) {
|
||||
if (canAddProperties(environment)) {
|
||||
logger.info("Devtools property defaults active! Set '" + ENABLED
|
||||
+ "' to 'false' to disable");
|
||||
|
|
|
@ -17,9 +17,8 @@
|
|||
package org.springframework.boot.devtools.restart;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.boot.devtools.DevtoolsEnablementDeducer;
|
||||
|
||||
/**
|
||||
* Default {@link RestartInitializer} that only enable initial restart when running a
|
||||
|
@ -32,26 +31,13 @@ import java.util.Set;
|
|||
*/
|
||||
public class DefaultRestartInitializer implements RestartInitializer {
|
||||
|
||||
private static final Set<String> SKIPPED_STACK_ELEMENTS;
|
||||
|
||||
static {
|
||||
Set<String> skipped = new LinkedHashSet<>();
|
||||
skipped.add("org.junit.runners.");
|
||||
skipped.add("org.junit.platform.");
|
||||
skipped.add("org.springframework.boot.test.");
|
||||
skipped.add("cucumber.runtime.");
|
||||
SKIPPED_STACK_ELEMENTS = Collections.unmodifiableSet(skipped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL[] getInitialUrls(Thread thread) {
|
||||
if (!isMain(thread)) {
|
||||
return null;
|
||||
}
|
||||
for (StackTraceElement element : thread.getStackTrace()) {
|
||||
if (isSkippedStackElement(element)) {
|
||||
return null;
|
||||
}
|
||||
if (!DevtoolsEnablementDeducer.shouldEnable(thread)) {
|
||||
return null;
|
||||
}
|
||||
return getUrls(thread);
|
||||
}
|
||||
|
@ -67,22 +53,6 @@ public class DefaultRestartInitializer implements RestartInitializer {
|
|||
.getClass().getName().contains("AppClassLoader");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific {@link StackTraceElement} should cause the initializer to be
|
||||
* skipped.
|
||||
* @param element the stack element to check
|
||||
* @return {@code true} if the stack element means that the initializer should be
|
||||
* skipped
|
||||
*/
|
||||
private boolean isSkippedStackElement(StackTraceElement element) {
|
||||
for (String skipped : SKIPPED_STACK_ELEMENTS) {
|
||||
if (element.getClassName().startsWith(skipped)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URLs that should be used with initialization.
|
||||
* @param thread the source thread
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
Loading…
Reference in New Issue