Rework ApplicationContext test helper
Rename `ContextLoader` to `ApplicationContextTester` and provide distinct subclasses for standard, web and reactive application contexts. Context callbacks now return AssertJ compatible contexts, allowing tests to run directly on context. For example: context.run((loaded) -> assertThat(loaded).hasBean("foo")); The returned context can now also represent a context that has failed to start (meaning that the `loadAndFail` methods are no longer needed): context.run((loaded) -> assertThat(loaded).hasFailed()); Configuration classes are loaded via the recently introduced `Configurations` class. This means that the tester no longer needs to be directly aware of auto-configuration concepts. See gh-9634pull/9800/merge
parent
c6f55ef46d
commit
24d086066b
@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.annotation.Configurations;
|
||||||
|
import org.springframework.boot.context.annotation.UserConfigurations;
|
||||||
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigRegistry;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tester utility design to manage the lifecycle of an {@link ApplicationContext} and
|
||||||
|
* provide AssertJ style assertions. The test is best used as a field of a test class,
|
||||||
|
* describing the shared configuration required for the test:
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* public class MyContextTests {
|
||||||
|
* private final ApplicationContextTester context = new ApplicationContextTester()
|
||||||
|
* .withPropertyValues("spring.foo=bar")
|
||||||
|
* .withUserConfiguration(MyConfiguration.class);
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The initialization above makes sure to register {@code MyConfiguration} for all tests
|
||||||
|
* and set the {@code spring.foo} property to {@code bar} unless specified otherwise.
|
||||||
|
* <p>
|
||||||
|
* Based on the configuration above, a specific test can simulate what will happen when
|
||||||
|
* the context runs, perhaps with overridden property values:
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* @Test
|
||||||
|
* public someTest() {
|
||||||
|
* this.contex.withPropertyValues("spring.foo=biz").run((loaded) -> {
|
||||||
|
* assertThat(loaded).containsSingleBean(MyBean.class);
|
||||||
|
* // other assertions
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* The test above has changed the {@code spring.foo} property to {@code biz} and is
|
||||||
|
* asserting that the context contains a single {@code MyBean} bean. The
|
||||||
|
* {@link #run(ContextConsumer) run} method takes a {@link ContextConsumer} that can apply
|
||||||
|
* assertions to the context. Upon completion, the context is automatically closed.
|
||||||
|
* <p>
|
||||||
|
* If the application context fails to start the {@code #run(ContextConsumer)} method is
|
||||||
|
* called with a "failed" application context. Calls to the context will throw an
|
||||||
|
* {@link IllegalStateException} and assertions that expect a running context will fail.
|
||||||
|
* The {@link ApplicationContextAssert#getFailure() getFailure()} assertion can be used if
|
||||||
|
* further checks are required on the cause of the failure: <pre class="code">
|
||||||
|
* @Test
|
||||||
|
* public someTest() {
|
||||||
|
* this.contex.withPropertyValues("spring.foo=fails").run((loaded) -> {
|
||||||
|
* assertThat(loaded).getFailure().hasCauseInstanceOf(BadPropertyExcepton.class);
|
||||||
|
* // other assertions
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param <SELF> The "self" type for this tester
|
||||||
|
* @param <C> The context type
|
||||||
|
* @param <A> The application context assertion provider
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
* @see ApplicationContextTester
|
||||||
|
* @see WebApplicationContextTester
|
||||||
|
* @see ReactiveWebApplicationContextTester
|
||||||
|
* @see ApplicationContextAssert
|
||||||
|
*/
|
||||||
|
abstract class AbstractApplicationContextTester<SELF extends AbstractApplicationContextTester<SELF, C, A>, C extends ConfigurableApplicationContext, A extends AssertProviderApplicationContext<C>> {
|
||||||
|
|
||||||
|
private final Supplier<C> contextFactory;
|
||||||
|
|
||||||
|
private final TestPropertyValues environmentProperties;
|
||||||
|
|
||||||
|
private final TestPropertyValues systemProperties;
|
||||||
|
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
|
||||||
|
private ApplicationContext parent;
|
||||||
|
|
||||||
|
private final List<Configurations> configurations = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link AbstractApplicationContextTester} instance.
|
||||||
|
* @param contextFactory the factory used to create the actual context
|
||||||
|
*/
|
||||||
|
protected AbstractApplicationContextTester(Supplier<C> contextFactory) {
|
||||||
|
Assert.notNull(contextFactory, "ContextFactory must not be null");
|
||||||
|
this.contextFactory = contextFactory;
|
||||||
|
this.environmentProperties = TestPropertyValues.empty();
|
||||||
|
this.systemProperties = TestPropertyValues.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified {@link Environment} property pairs. Key-value pairs can be
|
||||||
|
* specified with colon (":") or equals ("=") separators. Override matching keys that
|
||||||
|
* might have been specified previously.
|
||||||
|
* @param pairs the key-value pairs for properties that need to be added to the
|
||||||
|
* environment
|
||||||
|
* @return this instance
|
||||||
|
* @see TestPropertyValues
|
||||||
|
* @see #withSystemProperties(String...)
|
||||||
|
*/
|
||||||
|
public SELF withPropertyValues(String... pairs) {
|
||||||
|
Arrays.stream(pairs).forEach(this.environmentProperties::and);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified {@link Environment} property.
|
||||||
|
* @param name the name of the property
|
||||||
|
* @param value the value of the property
|
||||||
|
* @return this instance
|
||||||
|
* @see TestPropertyValues
|
||||||
|
* @see #withSystemProperties(String...)
|
||||||
|
*/
|
||||||
|
public SELF withPropertyValue(String name, String value) {
|
||||||
|
this.environmentProperties.and(name, value);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified {@link System} property pairs. Key-value pairs can be specified
|
||||||
|
* with colon (":") or equals ("=") separators. System properties are added before the
|
||||||
|
* context is {@link #run(ContextConsumer) run} and restored when the context is
|
||||||
|
* closed.
|
||||||
|
* @param pairs the key-value pairs for properties that need to be added to the system
|
||||||
|
* @return this instance
|
||||||
|
* @see TestPropertyValues
|
||||||
|
* @see #withSystemProperties(String...)
|
||||||
|
*/
|
||||||
|
public SELF withSystemProperties(String... pairs) {
|
||||||
|
Arrays.stream(pairs).forEach(this.systemProperties::and);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the specified {@link System} property. System properties are added before the
|
||||||
|
* context is {@link #run(ContextConsumer) run} and restored when the context is
|
||||||
|
* closed.
|
||||||
|
* @param name the property name
|
||||||
|
* @param value the property value
|
||||||
|
* @return this instance
|
||||||
|
* @see TestPropertyValues
|
||||||
|
* @see #withSystemProperties(String...)
|
||||||
|
*/
|
||||||
|
public SELF withSystemProperty(String name, String value) {
|
||||||
|
this.systemProperties.and(name, value);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 SELF withClassLoader(ClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the {@link ConfigurableApplicationContext#setParent(ApplicationContext)
|
||||||
|
* parent} of the {@link ApplicationContext}.
|
||||||
|
* @param parent the parent
|
||||||
|
* @return this instance
|
||||||
|
*/
|
||||||
|
public SELF withParent(ApplicationContext parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the specified user configuration classes with the
|
||||||
|
* {@link ApplicationContext}.
|
||||||
|
* @param configurationClasses the user configuration classes to add
|
||||||
|
* @return this instance
|
||||||
|
*/
|
||||||
|
public SELF withUserConfiguration(Class<?>... configurationClasses) {
|
||||||
|
return withConfiguration(UserConfigurations.of(configurationClasses));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the specified configuration classes with the {@link ApplicationContext}.
|
||||||
|
* @param configurations the configurations to add
|
||||||
|
* @return this instance
|
||||||
|
*/
|
||||||
|
public SELF withConfiguration(Configurations configurations) {
|
||||||
|
Assert.notNull(configurations, "Configurations must not be null");
|
||||||
|
this.configurations.add(configurations);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected final SELF self() {
|
||||||
|
return (SELF) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
||||||
|
* this loader. The context is consumed by the specified {@code consumer} and closed
|
||||||
|
* upon completion.
|
||||||
|
* @param consumer the consumer of the created {@link ApplicationContext}
|
||||||
|
*/
|
||||||
|
public void run(ContextConsumer<? super A> consumer) {
|
||||||
|
this.systemProperties.applyToSystemProperties(() -> {
|
||||||
|
try (A context = createAssertableContext()) {
|
||||||
|
accept(consumer, context);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private A createAssertableContext() {
|
||||||
|
ResolvableType resolvableType = ResolvableType
|
||||||
|
.forClass(AbstractApplicationContextTester.class, getClass());
|
||||||
|
Class<A> assertType = (Class<A>) resolvableType.resolveGeneric(1);
|
||||||
|
Class<C> contextType = (Class<C>) resolvableType.resolveGeneric(2);
|
||||||
|
return AssertProviderApplicationContext.get(assertType, contextType,
|
||||||
|
this::createAndLoadContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private C createAndLoadContext() {
|
||||||
|
C context = this.contextFactory.get();
|
||||||
|
try {
|
||||||
|
configureContext(context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
catch (RuntimeException ex) {
|
||||||
|
context.close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureContext(C context) {
|
||||||
|
if (this.parent != null) {
|
||||||
|
context.setParent(this.parent);
|
||||||
|
}
|
||||||
|
if (this.classLoader != null) {
|
||||||
|
Assert.isInstanceOf(DefaultResourceLoader.class, context);
|
||||||
|
((DefaultResourceLoader) context).setClassLoader(this.classLoader);
|
||||||
|
}
|
||||||
|
this.environmentProperties.applyTo(context);
|
||||||
|
Class<?>[] classes = Configurations.getClasses(this.configurations);
|
||||||
|
if (classes.length > 0) {
|
||||||
|
((AnnotationConfigRegistry) context).register(classes);
|
||||||
|
}
|
||||||
|
context.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void accept(ContextConsumer<? super A> consumer, A context) {
|
||||||
|
try {
|
||||||
|
consumer.accept(context);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
ReflectionUtils.rethrowRuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigRegistry;
|
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base implementation of {@link ContextLoader}.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the context to be loaded
|
|
||||||
* @param <L> the type of the loader
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
*/
|
|
||||||
class AbstractContextLoader<T extends ConfigurableApplicationContext, L extends AbstractContextLoader<T, ?>>
|
|
||||||
implements ContextLoader {
|
|
||||||
|
|
||||||
private final Map<String, String> systemProperties = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
private final List<String> env = new ArrayList<>();
|
|
||||||
|
|
||||||
private final Set<Class<?>> userConfigurations = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
private final LinkedList<Class<?>> autoConfigurations = new LinkedList<>();
|
|
||||||
|
|
||||||
private final Supplier<T> contextSupplier;
|
|
||||||
|
|
||||||
private ClassLoader classLoader;
|
|
||||||
|
|
||||||
private ApplicationContext parent;
|
|
||||||
|
|
||||||
protected AbstractContextLoader(Supplier<T> contextSupplier) {
|
|
||||||
this.contextSupplier = contextSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the specified system property prior to loading the context and restore its
|
|
||||||
* previous value once the consumer has been invoked and the context closed. If the
|
|
||||||
* {@code value} is {@code null} this removes any prior customization for that key.
|
|
||||||
* @param key the system property
|
|
||||||
* @param value the value (can be null to remove any existing customization)
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L 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 self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified property pairs. Key-value pairs can be specified with colon (":")
|
|
||||||
* or equals ("=") separators. Override matching keys that might have been specified
|
|
||||||
* previously.
|
|
||||||
* @param pairs the key-value pairs for properties that need to be added to the
|
|
||||||
* environment
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L env(String... pairs) {
|
|
||||||
if (!ObjectUtils.isEmpty(pairs)) {
|
|
||||||
this.env.addAll(Arrays.asList(pairs));
|
|
||||||
}
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified user configuration classes.
|
|
||||||
* @param configs the user configuration classes to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L config(Class<?>... configs) {
|
|
||||||
if (!ObjectUtils.isEmpty(configs)) {
|
|
||||||
this.userConfigurations.addAll(Arrays.asList(configs));
|
|
||||||
}
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public L parent(ApplicationContext parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified auto-configuration classes.
|
|
||||||
* @param autoConfigurations the auto-configuration classes to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L autoConfig(Class<?>... autoConfigurations) {
|
|
||||||
if (!ObjectUtils.isEmpty(autoConfigurations)) {
|
|
||||||
this.autoConfigurations.addAll(Arrays.asList(autoConfigurations));
|
|
||||||
}
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified auto-configurations at the beginning (in that order) so that it
|
|
||||||
* is applied before any other existing auto-configurations, but after any user
|
|
||||||
* configuration. If {@code A} and {@code B} are specified, {@code A} will be
|
|
||||||
* processed, then {@code B} and finally the rest of the existing auto-configuration.
|
|
||||||
* @param autoConfigurations the auto-configuration to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L autoConfigFirst(Class<?>... autoConfigurations) {
|
|
||||||
this.autoConfigurations.addAll(0, Arrays.asList(autoConfigurations));
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Customize the {@link ClassLoader} that the {@link ApplicationContext} should use.
|
|
||||||
* Customizing the {@link ClassLoader} is an effective manner to hide resources from
|
|
||||||
* the classpath.
|
|
||||||
* @param classLoader the classloader to use (can be null to use the default)
|
|
||||||
* @return this instance
|
|
||||||
* @see HidePackagesClassLoader
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public L classLoader(ClassLoader classLoader) {
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected final L self() {
|
|
||||||
return (L) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
|
||||||
* this loader. The context is consumed by the specified {@link ContextConsumer} and
|
|
||||||
* closed upon completion.
|
|
||||||
* @param consumer the consumer of the created {@link ApplicationContext}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void load(ContextConsumer consumer) {
|
|
||||||
doLoad(consumer::accept);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void doLoad(ContextHandler<T> contextHandler) {
|
|
||||||
try (ApplicationContextLifecycleHandler handler = new ApplicationContextLifecycleHandler()) {
|
|
||||||
try {
|
|
||||||
T ctx = handler.load();
|
|
||||||
contextHandler.handle(ctx);
|
|
||||||
}
|
|
||||||
catch (RuntimeException | AssertionError ex) {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"An unexpected error occurred: " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
|
||||||
* this loader that this expected to fail. If the context does not fail, an
|
|
||||||
* {@link AssertionError} is thrown. Otherwise the exception is consumed by the
|
|
||||||
* specified {@link Consumer} with no expectation on the type of the exception.
|
|
||||||
* @param consumer the consumer of the failure
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void loadAndFail(Consumer<Throwable> consumer) {
|
|
||||||
loadAndFail(Throwable.class, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
|
||||||
* this loader that this expected to fail. If the context does not fail, an
|
|
||||||
* {@link AssertionError} is thrown. If the exception does not match the specified
|
|
||||||
* {@code exceptionType}, an {@link AssertionError} is thrown as well. If the
|
|
||||||
* exception type matches, it is consumed by the specified {@link Consumer}.
|
|
||||||
* @param exceptionType the expected type of the failure
|
|
||||||
* @param consumer the consumer of the failure
|
|
||||||
* @param <E> the expected type of the failure
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <E extends Throwable> void loadAndFail(Class<E> exceptionType,
|
|
||||||
Consumer<E> consumer) {
|
|
||||||
try (ApplicationContextLifecycleHandler handler = new ApplicationContextLifecycleHandler()) {
|
|
||||||
handler.load();
|
|
||||||
throw new AssertionError("ApplicationContext should have failed");
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
assertThat(ex).as("Wrong application context failure exception")
|
|
||||||
.isInstanceOf(exceptionType);
|
|
||||||
consumer.accept(exceptionType.cast(ex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private T configureApplicationContext() {
|
|
||||||
T context = AbstractContextLoader.this.contextSupplier.get();
|
|
||||||
if (this.parent != null) {
|
|
||||||
context.setParent(this.parent);
|
|
||||||
}
|
|
||||||
if (this.classLoader != null) {
|
|
||||||
Assert.isInstanceOf(DefaultResourceLoader.class, context);
|
|
||||||
((DefaultResourceLoader) context).setClassLoader(this.classLoader);
|
|
||||||
}
|
|
||||||
if (!ObjectUtils.isEmpty(this.env)) {
|
|
||||||
TestPropertyValues.of(this.env.toArray(new String[this.env.size()]))
|
|
||||||
.applyTo(context);
|
|
||||||
}
|
|
||||||
if (!ObjectUtils.isEmpty(this.userConfigurations)) {
|
|
||||||
((AnnotationConfigRegistry) context).register(this.userConfigurations
|
|
||||||
.toArray(new Class<?>[this.userConfigurations.size()]));
|
|
||||||
}
|
|
||||||
if (!ObjectUtils.isEmpty(this.autoConfigurations)) {
|
|
||||||
LinkedHashSet<Class<?>> linkedHashSet = new LinkedHashSet<>(
|
|
||||||
this.autoConfigurations);
|
|
||||||
((AnnotationConfigRegistry) context).register(
|
|
||||||
linkedHashSet.toArray(new Class<?>[this.autoConfigurations.size()]));
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An internal callback interface that handles a concrete {@link ApplicationContext}
|
|
||||||
* type.
|
|
||||||
* @param <T> the type of the application context
|
|
||||||
*/
|
|
||||||
protected interface ContextHandler<T> {
|
|
||||||
|
|
||||||
void handle(T context) throws Throwable;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the lifecycle of the {@link ApplicationContext}.
|
|
||||||
*/
|
|
||||||
private class ApplicationContextLifecycleHandler implements Closeable {
|
|
||||||
|
|
||||||
private final Map<String, String> customSystemProperties;
|
|
||||||
|
|
||||||
private final Map<String, String> previousSystemProperties = new HashMap<>();
|
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
|
||||||
|
|
||||||
ApplicationContextLifecycleHandler() {
|
|
||||||
this.customSystemProperties = new HashMap<>(
|
|
||||||
AbstractContextLoader.this.systemProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T load() {
|
|
||||||
setCustomSystemProperties();
|
|
||||||
T context = configureApplicationContext();
|
|
||||||
context.refresh();
|
|
||||||
this.context = context;
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
if (this.context != null) {
|
|
||||||
this.context.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
unsetCustomSystemProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCustomSystemProperties() {
|
|
||||||
this.customSystemProperties.forEach((key, value) -> {
|
|
||||||
String previous = System.setProperty(key, value);
|
|
||||||
this.previousSystemProperties.put(key, previous);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unsetCustomSystemProperties() {
|
|
||||||
this.previousSystemProperties.forEach((key, value) -> {
|
|
||||||
if (value != null) {
|
|
||||||
System.setProperty(key, value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
System.clearProperty(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,374 @@
|
|||||||
|
/*
|
||||||
|
* 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.assertj.core.api.AbstractAssert;
|
||||||
|
import org.assertj.core.api.AbstractObjectArrayAssert;
|
||||||
|
import org.assertj.core.api.AbstractObjectAssert;
|
||||||
|
import org.assertj.core.api.AbstractThrowableAssert;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.assertj.core.api.MapAssert;
|
||||||
|
import org.assertj.core.error.BasicErrorMessageFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AspectJ {@link org.assertj.core.api.Assert assertions} that can be applied to an
|
||||||
|
* {@link ApplicationContext}.
|
||||||
|
*
|
||||||
|
* @param <C> The application context type
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
* @see ApplicationContextTester
|
||||||
|
* @see AssertableApplicationContext
|
||||||
|
*/
|
||||||
|
public class ApplicationContextAssert<C extends ApplicationContext>
|
||||||
|
extends AbstractAssert<ApplicationContextAssert<C>, C> {
|
||||||
|
|
||||||
|
private final Throwable startupFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ApplicationContextAssert} instance.
|
||||||
|
* @param applicationContext the source application context
|
||||||
|
* @param startupFailure the startup failure or {@code null}
|
||||||
|
*/
|
||||||
|
ApplicationContextAssert(C applicationContext, Throwable startupFailure) {
|
||||||
|
super(applicationContext, ApplicationContextAssert.class);
|
||||||
|
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||||
|
this.startupFailure = startupFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application context contains a bean with the given name.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).hasBean("fooBean"); </pre>
|
||||||
|
* @param name the name of the bean
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context does not contain a bean with the
|
||||||
|
* given name
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> hasBean(String name) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have bean named:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), name));
|
||||||
|
}
|
||||||
|
if (findBean(name) == null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have bean named:%n <%s>%nbut found no such bean",
|
||||||
|
getApplicationContext(), name));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application context contains a single bean with the given type.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).hasSingleBean(Foo.class); </pre>
|
||||||
|
* @param type the bean type
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context does no beans of the given type
|
||||||
|
* @throws AssertionError if the application context contains multiple beans of the
|
||||||
|
* given type
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> hasSingleBean(Class<?> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have a single bean of type:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), type));
|
||||||
|
}
|
||||||
|
String[] names = getApplicationContext().getBeanNamesForType(type);
|
||||||
|
if (names.length == 0) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have a single bean of type:%n <%s>%nbut found no beans of that type",
|
||||||
|
getApplicationContext(), type));
|
||||||
|
}
|
||||||
|
if (names.length > 1) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have a single bean of type:%n <%s>%nbut found:%n <%s>",
|
||||||
|
getApplicationContext(), type, names));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application context does not contain any beans of the given type.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).doesNotHaveBean(Foo.class); </pre>
|
||||||
|
* @param type the bean type
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context contains any beans of the given
|
||||||
|
* type
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> doesNotHaveBean(Class<?> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nnot to have any beans of type:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), type));
|
||||||
|
}
|
||||||
|
String[] names = getApplicationContext().getBeanNamesForType(type);
|
||||||
|
if (names.length > 0) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nnot to have a beans of type:%n <%s>%nbut found:%n <%s>",
|
||||||
|
getApplicationContext(), type, names));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application context does not contain a beans of the given name.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).doesNotHaveBean("fooBean"); </pre>
|
||||||
|
* @param name the name of the bean
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context contains a beans of the given
|
||||||
|
* name
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> doesNotHaveBean(String name) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nnot to have any beans of name:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), name));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Object bean = getApplicationContext().getBean(name);
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nnot to have a bean of name:%n <%s>%nbut found:%n <%s>",
|
||||||
|
getApplicationContext(), name, bean));
|
||||||
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the beans names of the given type from the application context, the names
|
||||||
|
* becoming the object array under test.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getBeanNames(Foo.class).containsOnly("fooBean"); </pre>
|
||||||
|
* @param <T> the bean type
|
||||||
|
* @param type the bean type
|
||||||
|
* @return array assertions for the bean names
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
*/
|
||||||
|
public <T> AbstractObjectArrayAssert<?, String> getBeanNames(Class<T> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto get beans names with type:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), type));
|
||||||
|
}
|
||||||
|
return Assertions.assertThat(getApplicationContext().getBeanNamesForType(type))
|
||||||
|
.as("Bean names of type <%s> from <%s>", type, getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a single bean of the given type from the application context, the bean
|
||||||
|
* becoming the object under test. If no beans of the specified type can be found an
|
||||||
|
* assert on {@code null} is returned.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getBean(Foo.class).isInstanceOf(DefaultFoo.class);
|
||||||
|
* assertThat(context).getBean(Bar.class).isNull();</pre>
|
||||||
|
* @param <T> the bean type
|
||||||
|
* @param type the bean type
|
||||||
|
* @return bean assertions for the bean, or an assert on {@code null} if the no bean
|
||||||
|
* is found
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context contains multiple beans of the
|
||||||
|
* given type
|
||||||
|
*/
|
||||||
|
public <T> AbstractObjectAssert<?, T> getBean(Class<T> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto contain bean of type:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), type));
|
||||||
|
}
|
||||||
|
String[] names = getApplicationContext().getBeanNamesForType(type);
|
||||||
|
if (names.length > 1) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nsingle bean of type:%n <%s>%nbut found:%n <%s>",
|
||||||
|
getApplicationContext(), type, names));
|
||||||
|
}
|
||||||
|
T bean = (names.length == 0 ? null
|
||||||
|
: getApplicationContext().getBean(names[0], type));
|
||||||
|
return Assertions.assertThat(bean).as("Bean of type <%s> from <%s>", type,
|
||||||
|
getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a single bean of the given name from the application context, the bean
|
||||||
|
* becoming the object under test. If no bean of the specified name can be found an
|
||||||
|
* assert on {@code null} is returned.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getBean("foo").isInstanceOf(Foo.class);
|
||||||
|
* assertThat(context).getBean("foo").isNull();</pre>
|
||||||
|
* @param name the name of the bean
|
||||||
|
* @return bean assertions for the bean, or an assert on {@code null} if the no bean
|
||||||
|
* is found
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
*/
|
||||||
|
public AbstractObjectAssert<?, Object> getBean(String name) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto contain a bean of name:%n <%s>%nbut context failed to start",
|
||||||
|
getApplicationContext(), name));
|
||||||
|
}
|
||||||
|
Object bean = findBean(name);
|
||||||
|
return Assertions.assertThat(bean).as("Bean of name <%s> from <%s>", name,
|
||||||
|
getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a single bean of the given name and type from the application context, the
|
||||||
|
* bean becoming the object under test. If no bean of the specified name can be found
|
||||||
|
* an assert on {@code null} is returned.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getBean("foo", Foo.class).isInstanceOf(DefaultFoo.class);
|
||||||
|
* assertThat(context).getBean("foo", Foo.class).isNull();</pre>
|
||||||
|
* @param <T> the bean type
|
||||||
|
* @param name the name of the bean
|
||||||
|
* @param type the bean type
|
||||||
|
* @return bean assertions for the bean, or an assert on {@code null} if the no bean
|
||||||
|
* is found
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
* @throws AssertionError if the application context contains a bean with the given
|
||||||
|
* name but a different type
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto contain a bean of name:%n <%s> (%s)%nbut context failed to start",
|
||||||
|
getApplicationContext(), name, type));
|
||||||
|
}
|
||||||
|
Object bean = findBean(name);
|
||||||
|
if (bean != null && type != null && !type.isInstance(bean)) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto contain a bean of name:%n <%s> (%s)%nbut found:%n <%s> of type <%s>",
|
||||||
|
getApplicationContext(), name, type, bean, bean.getClass()));
|
||||||
|
}
|
||||||
|
return Assertions.assertThat((T) bean).as(
|
||||||
|
"Bean of name <%s> and type <%s> from <%s>", name, type,
|
||||||
|
getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object findBean(String name) {
|
||||||
|
try {
|
||||||
|
return getApplicationContext().getBean(name);
|
||||||
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a map bean names and instances of the given type from the application
|
||||||
|
* context, the map becoming the object under test. If no bean of the specified type
|
||||||
|
* can be found an assert on an empty {@code map} is returned.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getBeans(Foo.class).containsKey("foo");
|
||||||
|
* </pre>
|
||||||
|
* @param <T> the bean type
|
||||||
|
* @param type the bean type
|
||||||
|
* @return bean assertions for the beans, or an assert on an empty {@code map} if the
|
||||||
|
* no beans are found
|
||||||
|
* @throws AssertionError if the application context did not start
|
||||||
|
*/
|
||||||
|
public <T> MapAssert<String, T> getBeans(Class<T> type) {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto get beans of type:%n <%s> (%s)%nbut context failed to start",
|
||||||
|
getApplicationContext(), type, type));
|
||||||
|
}
|
||||||
|
return Assertions.assertThat(getApplicationContext().getBeansOfType(type))
|
||||||
|
.as("Beans of type <%s> from <%s>", type, getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the failure that stopped the application context from running, the failure
|
||||||
|
* becoming the object under test.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code">
|
||||||
|
* assertThat(context).getFailure().containsMessage("missing bean");
|
||||||
|
* </pre>
|
||||||
|
* @return assertions on the cause of the failure
|
||||||
|
* @throws AssertionError if the application context started without a failure
|
||||||
|
*/
|
||||||
|
public AbstractThrowableAssert<?, ? extends Throwable> getFailure() {
|
||||||
|
hasFailed();
|
||||||
|
return assertThat(this.startupFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application has failed to start.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code"> assertThat(context).hasFailed();
|
||||||
|
* </pre>
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context started without a failure
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> hasFailed() {
|
||||||
|
if (this.startupFailure == null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have failed%nbut context started successfully",
|
||||||
|
getApplicationContext()));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the application has not failed to start.
|
||||||
|
* <p>
|
||||||
|
* Example: <pre class="code"> assertThat(context).hasNotFailed();
|
||||||
|
* </pre>
|
||||||
|
* @return {@code this} assertion object.
|
||||||
|
* @throws AssertionError if the application context failed to start
|
||||||
|
*/
|
||||||
|
public ApplicationContextAssert<C> hasNotFailed() {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throwAssertionError(new BasicErrorMessageFactory(
|
||||||
|
"%nExpecting:%n <%s>%nto have not failed:%nbut context failed to start",
|
||||||
|
getApplicationContext()));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final C getApplicationContext() {
|
||||||
|
return this.actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Throwable getStartupFailure() {
|
||||||
|
return this.startupFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link AbstractApplicationContextTester ApplicationContext tester} for a standard,
|
||||||
|
* non-web environment {@link ConfigurableApplicationContext}.
|
||||||
|
* <p>
|
||||||
|
* See {@link AbstractApplicationContextTester} for details.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class ApplicationContextTester extends
|
||||||
|
AbstractApplicationContextTester<ApplicationContextTester, ConfigurableApplicationContext, AssertableApplicationContext> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ApplicationContextTester} instance using an
|
||||||
|
* {@link AnnotationConfigApplicationContext} as the underlying source.
|
||||||
|
*/
|
||||||
|
public ApplicationContextTester() {
|
||||||
|
this(AnnotationConfigApplicationContext::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ApplicationContextTester} instance using the specified
|
||||||
|
* {@code contextFactory} as the underlying source.
|
||||||
|
* @param contextFactory a supplier that returns a new instance on each call
|
||||||
|
*/
|
||||||
|
public ApplicationContextTester(
|
||||||
|
Supplier<ConfigurableApplicationContext> contextFactory) {
|
||||||
|
super(contextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.reflect.Proxy;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.assertj.core.api.AssertProvider;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link ApplicationContext} that additionally supports AssertJ style assertions. Can
|
||||||
|
* be used to decorate and existing application context or an application context that
|
||||||
|
* failed to start.
|
||||||
|
* <p>
|
||||||
|
* Assertions can be applied using the standard AssertJ {@code assertThat(...)} style (see
|
||||||
|
* {@link ApplicationContextAssert} for a complete list). For example: <pre class="code">
|
||||||
|
* assertThat(applicationContext).hasSingleBean(MyBean.class);
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If the original {@link ApplicationContext} is needed for any reason the
|
||||||
|
* {@link #getSourceApplicationContext()} method can be used.
|
||||||
|
* <p>
|
||||||
|
* Any {@link ApplicationContext} method called on a context that has failed to start will
|
||||||
|
* throw an {@link IllegalStateException}.
|
||||||
|
*
|
||||||
|
* @param <C> The application context type
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @see AssertableApplicationContext
|
||||||
|
* @see AssertableWebApplicationContext
|
||||||
|
* @see AssertableReactiveWebApplicationContext
|
||||||
|
* @see ApplicationContextAssert
|
||||||
|
*/
|
||||||
|
interface AssertProviderApplicationContext<C extends ApplicationContext> extends
|
||||||
|
ApplicationContext, AssertProvider<ApplicationContextAssert<C>>, Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an assert for AspectJ.
|
||||||
|
* @return an AspectJ assert
|
||||||
|
* @deprecated use standard AssertJ {@code assertThat(context)...} calls instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
ApplicationContextAssert<C> assertThat();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the original source {@link ApplicationContext}.
|
||||||
|
* @return the source application context
|
||||||
|
* @throws IllegalStateException if the source context failed to start
|
||||||
|
*/
|
||||||
|
C getSourceApplicationContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the original source {@link ApplicationContext}, casting it to the requested
|
||||||
|
* type.
|
||||||
|
* @param <T> the context type
|
||||||
|
* @param requiredType the required context type
|
||||||
|
* @return the source application context
|
||||||
|
* @throws IllegalStateException if the source context failed to start
|
||||||
|
*/
|
||||||
|
<T extends C> T getSourceApplicationContext(Class<T> requiredType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the failure that caused application context to fail or {@code null} if the
|
||||||
|
* context started without issue.
|
||||||
|
* @return the startup failure or {@code null}
|
||||||
|
*/
|
||||||
|
Throwable getStartupFailure();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link AssertProviderApplicationContext} instance.
|
||||||
|
* @param <T> the assert provider type
|
||||||
|
* @param <C> the context type
|
||||||
|
* @param type the type of {@link AssertProviderApplicationContext} required (must be
|
||||||
|
* an interface)
|
||||||
|
* @param contextType the type of {@link ApplicationContext} being managed (must be an
|
||||||
|
* interface)
|
||||||
|
* @param contextSupplier a supplier that will either return a fully configured
|
||||||
|
* {@link ApplicationContext} or throw an exception if the context fails to start.
|
||||||
|
* @return a {@link AssertProviderApplicationContext} instance
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static <T extends AssertProviderApplicationContext<C>, C extends ApplicationContext> T get(
|
||||||
|
Class<T> type, Class<? extends C> contextType,
|
||||||
|
Supplier<? extends C> contextSupplier) {
|
||||||
|
Assert.notNull(type, "Type must not be null");
|
||||||
|
Assert.isTrue(type.isInterface(), "Type must be an interface");
|
||||||
|
Assert.notNull(contextType, "ContextType must not be null");
|
||||||
|
Assert.isTrue(contextType.isInterface(), "ContextType must be an interface");
|
||||||
|
Class<?>[] interfaces = { type, contextType };
|
||||||
|
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
|
||||||
|
interfaces, new AssertProviderApplicationContextInvocationHandler(
|
||||||
|
contextType, contextSupplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link InvocationHandler} used by {@link AssertProviderApplicationContext} generated
|
||||||
|
* proxies.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class AssertProviderApplicationContextInvocationHandler implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Class<?> applicationContextType;
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final RuntimeException startupFailure;
|
||||||
|
|
||||||
|
AssertProviderApplicationContextInvocationHandler(Class<?> applicationContextType,
|
||||||
|
Supplier<?> contextSupplier) {
|
||||||
|
this.applicationContextType = applicationContextType;
|
||||||
|
Object contextOrStartupFailure = getContextOrStartupFailure(contextSupplier);
|
||||||
|
if (contextOrStartupFailure instanceof RuntimeException) {
|
||||||
|
this.applicationContext = null;
|
||||||
|
this.startupFailure = (RuntimeException) contextOrStartupFailure;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.applicationContext = (ApplicationContext) contextOrStartupFailure;
|
||||||
|
this.startupFailure = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getContextOrStartupFailure(Supplier<?> contextSupplier) {
|
||||||
|
try {
|
||||||
|
return contextSupplier.get();
|
||||||
|
}
|
||||||
|
catch (RuntimeException ex) {
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
if (isToString(method)) {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
if (isGetSourceContext(method)) {
|
||||||
|
return getSourceContext(args);
|
||||||
|
}
|
||||||
|
if (isGetStartupFailure(method)) {
|
||||||
|
return getStartupFailure();
|
||||||
|
}
|
||||||
|
if (isAssertThat(method)) {
|
||||||
|
return getAssertThat(proxy);
|
||||||
|
}
|
||||||
|
if (isCloseMethod(method)) {
|
||||||
|
return invokeClose();
|
||||||
|
}
|
||||||
|
return invokeApplicationContextMethod(method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isToString(Method method) {
|
||||||
|
return ("toString".equals(method.getName()) && method.getParameterCount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
return "Unstarted application context "
|
||||||
|
+ this.applicationContextType.getName() + "[startupFailure="
|
||||||
|
+ this.startupFailure.getClass().getName() + "]";
|
||||||
|
}
|
||||||
|
ToStringBuilder builder = new ToStringBuilder(this.applicationContext)
|
||||||
|
.append("id", this.applicationContext.getId())
|
||||||
|
.append("applicationName", this.applicationContext.getApplicationName())
|
||||||
|
.append("beanDefinitionCount",
|
||||||
|
this.applicationContext.getBeanDefinitionCount());
|
||||||
|
return "Started application " + builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGetSourceContext(Method method) {
|
||||||
|
return "getSourceApplicationContext".equals(method.getName())
|
||||||
|
&& ((method.getParameterCount() == 0) || Arrays.equals(
|
||||||
|
new Class<?>[] { Class.class }, method.getParameterTypes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getSourceContext(Object[] args) {
|
||||||
|
ApplicationContext context = getStartedApplicationContext();
|
||||||
|
if (!ObjectUtils.isEmpty(args)) {
|
||||||
|
Assert.isInstanceOf((Class<?>) args[0], context);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGetStartupFailure(Method method) {
|
||||||
|
return ("getStartupFailure".equals(method.getName())
|
||||||
|
&& method.getParameterCount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getStartupFailure() {
|
||||||
|
return this.startupFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAssertThat(Method method) {
|
||||||
|
return ("assertThat".equals(method.getName()) && method.getParameterCount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getAssertThat(Object proxy) {
|
||||||
|
return new ApplicationContextAssert<ApplicationContext>(
|
||||||
|
(ApplicationContext) proxy, this.startupFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCloseMethod(Method method) {
|
||||||
|
return ("close".equals(method.getName()) && method.getParameterCount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object invokeClose() throws IOException {
|
||||||
|
if (this.applicationContext instanceof Closeable) {
|
||||||
|
((Closeable) this.applicationContext).close();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object invokeApplicationContextMethod(Method method, Object[] args)
|
||||||
|
throws Throwable {
|
||||||
|
try {
|
||||||
|
return method.invoke(getStartedApplicationContext(), args);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException ex) {
|
||||||
|
throw ex.getTargetException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApplicationContext getStartedApplicationContext() {
|
||||||
|
if (this.startupFailure != null) {
|
||||||
|
throw new IllegalStateException(toString() + " failed to start",
|
||||||
|
this.startupFailure);
|
||||||
|
}
|
||||||
|
return this.applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link ApplicationContext} that additionally supports AssertJ style assertions. Can
|
||||||
|
* be used to decorate and existing application context or an application context that
|
||||||
|
* failed to start.
|
||||||
|
* <p>
|
||||||
|
* See {@link AssertProviderApplicationContext} for more details.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
* @see ApplicationContextTester
|
||||||
|
* @see ApplicationContext
|
||||||
|
*/
|
||||||
|
public interface AssertableApplicationContext
|
||||||
|
extends AssertProviderApplicationContext<ConfigurableApplicationContext> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link AssertableApplicationContext} instance.
|
||||||
|
* @param contextSupplier a supplier that will either return a fully configured
|
||||||
|
* {@link ConfigurableApplicationContext} or throw an exception if the context fails
|
||||||
|
* to start.
|
||||||
|
* @return an {@link AssertableApplicationContext} instance
|
||||||
|
*/
|
||||||
|
static AssertableApplicationContext get(
|
||||||
|
Supplier<? extends ConfigurableApplicationContext> contextSupplier) {
|
||||||
|
return AssertProviderApplicationContext.get(AssertableApplicationContext.class,
|
||||||
|
ConfigurableApplicationContext.class, contextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebApplicationContext;
|
||||||
|
import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ReactiveWebApplicationContext} that additionally supports AssertJ style
|
||||||
|
* assertions. Can be used to decorate and existing reactive web application context or an
|
||||||
|
* application context that failed to start.
|
||||||
|
* <p>
|
||||||
|
* See {@link AssertProviderApplicationContext} for more details.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
* @see ReactiveWebApplicationContext
|
||||||
|
* @see ReactiveWebApplicationContext
|
||||||
|
*/
|
||||||
|
public interface AssertableReactiveWebApplicationContext extends
|
||||||
|
AssertProviderApplicationContext<ConfigurableReactiveWebApplicationContext>,
|
||||||
|
ReactiveWebApplicationContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link AssertableReactiveWebApplicationContext}
|
||||||
|
* instance.
|
||||||
|
* @param contextSupplier a supplier that will either return a fully configured
|
||||||
|
* {@link ConfigurableReactiveWebApplicationContext} or throw an exception if the
|
||||||
|
* context fails to start.
|
||||||
|
* @return a {@link AssertableReactiveWebApplicationContext} instance
|
||||||
|
*/
|
||||||
|
static AssertableReactiveWebApplicationContext get(
|
||||||
|
Supplier<? extends ConfigurableReactiveWebApplicationContext> contextSupplier) {
|
||||||
|
return AssertProviderApplicationContext.get(
|
||||||
|
AssertableReactiveWebApplicationContext.class,
|
||||||
|
ConfigurableReactiveWebApplicationContext.class, contextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link WebApplicationContext} that additionally supports AssertJ style assertions.
|
||||||
|
* Can be used to decorate and existing servlet web application context or an application
|
||||||
|
* context that failed to start.
|
||||||
|
* <p>
|
||||||
|
* See {@link AssertProviderApplicationContext} for more details.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
* @see WebApplicationContextTester
|
||||||
|
* @see WebApplicationContext
|
||||||
|
*/
|
||||||
|
public interface AssertableWebApplicationContext
|
||||||
|
extends AssertProviderApplicationContext<ConfigurableWebApplicationContext>,
|
||||||
|
WebApplicationContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link AssertableWebApplicationContext} instance.
|
||||||
|
* @param contextSupplier a supplier that will either return a fully configured
|
||||||
|
* {@link ConfigurableWebApplicationContext} or throw an exception if the context
|
||||||
|
* fails to start.
|
||||||
|
* @return a {@link AssertableWebApplicationContext} instance
|
||||||
|
*/
|
||||||
|
static AssertableWebApplicationContext get(
|
||||||
|
Supplier<? extends ConfigurableWebApplicationContext> contextSupplier) {
|
||||||
|
return AssertProviderApplicationContext.get(AssertableWebApplicationContext.class,
|
||||||
|
ConfigurableWebApplicationContext.class, contextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
|
||||||
import org.springframework.mock.web.MockServletContext;
|
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* public class FooAutoConfigurationTests {
|
|
||||||
*
|
|
||||||
* private final ContextLoader contextLoader = ContextLoader.standard()
|
|
||||||
* .autoConfig(FooAutoConfiguration.class).env("spring.foo=bar");
|
|
||||||
*
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 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:
|
|
||||||
*
|
|
||||||
* <pre class="code">
|
|
||||||
* public class FooAutoConfigurationTests {
|
|
||||||
*
|
|
||||||
* @Test
|
|
||||||
* public someTest() {
|
|
||||||
* this.contextLoader.config(UserConfig.class).env("spring.foo=biz")
|
|
||||||
* .load(context -> {
|
|
||||||
* // assertions using the context
|
|
||||||
* });
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The test above includes an extra {@code UserConfig} class that is guaranteed to be
|
|
||||||
* processed <strong>before</strong> 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.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Web environment can easily be simulated using the {@link #servletWeb()} and
|
|
||||||
* {@link #reactiveWeb()} factory methods.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 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 interface ContextLoader {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
ContextLoader systemProperty(String key, String value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified property pairs. Key-value pairs can be specified with colon (":")
|
|
||||||
* or equals ("=") separators. Override matching keys that might have been specified
|
|
||||||
* previously.
|
|
||||||
* @param pairs the key-value pairs for properties that need to be added to the
|
|
||||||
* environment
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
ContextLoader env(String... pairs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified user configuration classes.
|
|
||||||
* @param configs the user configuration classes to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
ContextLoader config(Class<?>... configs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified auto-configuration classes.
|
|
||||||
* @param autoConfigurations the auto-configuration classes to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
ContextLoader autoConfig(Class<?>... autoConfigurations);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified auto-configurations at the beginning (in that order) so that it
|
|
||||||
* is applied before any other existing auto-configurations, but after any user
|
|
||||||
* configuration. If {@code A} and {@code B} are specified, {@code A} will be
|
|
||||||
* processed, then {@code B} and finally the rest of the existing auto-configuration.
|
|
||||||
* @param autoConfigurations the auto-configuration to add
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
ContextLoader autoConfigFirst(Class<?>... autoConfigurations);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
ContextLoader classLoader(ClassLoader classLoader);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the
|
|
||||||
* {@link org.springframework.context.ConfigurableApplicationContext#setParent(ApplicationContext)
|
|
||||||
* parent} of the {@link ApplicationContext}.
|
|
||||||
*
|
|
||||||
* @param parent the parent
|
|
||||||
* @return this instance
|
|
||||||
*/
|
|
||||||
ContextLoader parent(ApplicationContext parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
|
||||||
* this loader. The context is consumed by the specified {@code consumer} and closed
|
|
||||||
* upon completion.
|
|
||||||
* @param consumer the consumer of the created {@link ApplicationContext}
|
|
||||||
*/
|
|
||||||
void load(ContextConsumer 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. 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
|
|
||||||
*/
|
|
||||||
void loadAndFail(Consumer<Throwable> consumer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ApplicationContext} based on the current state of
|
|
||||||
* this loader that this expected to fail. If the context does not fail, an
|
|
||||||
* {@link AssertionError} is thrown. If the exception does not match the specified
|
|
||||||
* {@code exceptionType}, an {@link AssertionError} is thrown as well. If the
|
|
||||||
* exception type matches, it is consumed by the specified {@link Consumer}.
|
|
||||||
* @param exceptionType the expected type of the failure
|
|
||||||
* @param consumer the consumer of the failure
|
|
||||||
* @param <E> the expected type of the failure
|
|
||||||
*/
|
|
||||||
<E extends Throwable> void loadAndFail(Class<E> exceptionType, Consumer<E> consumer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@code ContextLoader} that will load a standard
|
|
||||||
* {@link AnnotationConfigApplicationContext}.
|
|
||||||
* @return the context loader
|
|
||||||
*/
|
|
||||||
static StandardContextLoader standard() {
|
|
||||||
return new StandardContextLoader(AnnotationConfigApplicationContext::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@code ContextLoader} that will load a
|
|
||||||
* {@link AnnotationConfigWebApplicationContext}.
|
|
||||||
* @return the context loader
|
|
||||||
*/
|
|
||||||
static ServletWebContextLoader servletWeb() {
|
|
||||||
return new ServletWebContextLoader(() -> {
|
|
||||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
|
||||||
context.setServletContext(new MockServletContext());
|
|
||||||
return context;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@code ContextLoader} that will load a
|
|
||||||
* {@link GenericReactiveWebApplicationContext}.
|
|
||||||
* @return the context loader
|
|
||||||
*/
|
|
||||||
static ReactiveWebContextLoader reactiveWeb() {
|
|
||||||
return new ReactiveWebContextLoader(GenericReactiveWebApplicationContext::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebApplicationContext;
|
||||||
|
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link AbstractApplicationContextTester ApplicationContext tester} for a
|
||||||
|
* {@link ConfigurableReactiveWebApplicationContext}.
|
||||||
|
* <p>
|
||||||
|
* See {@link AbstractApplicationContextTester} for details.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public final class ReactiveWebApplicationContextTester extends
|
||||||
|
AbstractApplicationContextTester<ReactiveWebApplicationContextTester, ConfigurableReactiveWebApplicationContext, AssertableReactiveWebApplicationContext> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ReactiveWebApplicationContextTester} instance using a
|
||||||
|
* {@link GenericReactiveWebApplicationContext} as the underlying source.
|
||||||
|
*/
|
||||||
|
public ReactiveWebApplicationContextTester() {
|
||||||
|
this(GenericReactiveWebApplicationContext::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link ApplicationContextTester} instance using the specified
|
||||||
|
* {@code contextFactory} as the underlying source.
|
||||||
|
* @param contextFactory a supplier that returns a new instance on each call
|
||||||
|
*/
|
||||||
|
public ReactiveWebApplicationContextTester(
|
||||||
|
Supplier<ConfigurableReactiveWebApplicationContext> contextFactory) {
|
||||||
|
super(contextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link ContextLoader} that simulates a {@link AnnotationConfigWebApplicationContext}
|
|
||||||
* which can be useful to test components that require a servlet web application.
|
|
||||||
*
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
public final class ServletWebContextLoader extends
|
|
||||||
AbstractContextLoader<AnnotationConfigWebApplicationContext, ServletWebContextLoader> {
|
|
||||||
|
|
||||||
ServletWebContextLoader(
|
|
||||||
Supplier<AnnotationConfigWebApplicationContext> contextSupplier) {
|
|
||||||
super(contextSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and refresh a new {@link ConfigurableWebApplicationContext} based on the
|
|
||||||
* current state of this loader. The context is consumed by the specified
|
|
||||||
* {@link WebMvcContextConsumer consumer} and closed upon completion.
|
|
||||||
* @param consumer the consumer of the created
|
|
||||||
* {@link ConfigurableWebApplicationContext}
|
|
||||||
*/
|
|
||||||
public void loadWeb(WebMvcContextConsumer consumer) {
|
|
||||||
doLoad(consumer::accept);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link AbstractApplicationContextTester ApplicationContext tester} for a Servlet
|
||||||
|
* based {@link ConfigurableWebApplicationContext}.
|
||||||
|
* <p>
|
||||||
|
* See {@link AbstractApplicationContextTester} for details.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public final class WebApplicationContextTester extends
|
||||||
|
AbstractApplicationContextTester<WebApplicationContextTester, ConfigurableWebApplicationContext, AssertableWebApplicationContext> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link WebApplicationContextTester} instance using an
|
||||||
|
* {@link AnnotationConfigWebApplicationContext} with a {@link MockServletContext} as
|
||||||
|
* the underlying source.
|
||||||
|
* @see #withMockServletContext(Supplier)
|
||||||
|
*/
|
||||||
|
public WebApplicationContextTester() {
|
||||||
|
this(withMockServletContext(AnnotationConfigWebApplicationContext::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link WebApplicationContextTester} instance using the specified
|
||||||
|
* {@code contextFactory} as the underlying source.
|
||||||
|
* @param contextFactory a supplier that returns a new instance on each call
|
||||||
|
*/
|
||||||
|
public WebApplicationContextTester(
|
||||||
|
Supplier<ConfigurableWebApplicationContext> contextFactory) {
|
||||||
|
super(contextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate the specified {@code contextFactory} to set a {@link MockServletContext}
|
||||||
|
* on each newly created {@link WebApplicationContext}.
|
||||||
|
* @param contextFactory the context factory to decorate
|
||||||
|
* @return an updated supplier that will set the {@link MockServletContext}
|
||||||
|
*/
|
||||||
|
public static Supplier<ConfigurableWebApplicationContext> withMockServletContext(
|
||||||
|
Supplier<ConfigurableWebApplicationContext> contextFactory) {
|
||||||
|
return (contextFactory == null ? null : () -> {
|
||||||
|
ConfigurableWebApplicationContext context = contextFactory.get();
|
||||||
|
context.setServletContext(new MockServletContext());
|
||||||
|
return context;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.UUID;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.annotation.UserConfigurations;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract tests for {@link AbstractApplicationContextTester} implementations.
|
||||||
|
*
|
||||||
|
* @param <T> The tester type
|
||||||
|
* @param <C> the context type
|
||||||
|
* @param <A> the assertable context type
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public abstract class AbstractApplicationContextTesterTests<T extends AbstractApplicationContextTester<T, C, A>, C extends ConfigurableApplicationContext, A extends AssertProviderApplicationContext<C>> {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithSystemPropertiesShouldSetAndRemoveProperties() {
|
||||||
|
String key = "test." + UUID.randomUUID().toString();
|
||||||
|
assertThat(System.getProperties().containsKey(key)).isFalse();
|
||||||
|
get().withSystemProperties(key + "=value").run(loaded -> {
|
||||||
|
assertThat(System.getProperties()).containsEntry(key, "value");
|
||||||
|
});
|
||||||
|
assertThat(System.getProperties().containsKey(key)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithSystemPropertiesWhenContextFailsShouldRemoveProperties()
|
||||||
|
throws Exception {
|
||||||
|
String key = "test." + UUID.randomUUID().toString();
|
||||||
|
assertThat(System.getProperties().containsKey(key)).isFalse();
|
||||||
|
get().withSystemProperties(key + "=value")
|
||||||
|
.withUserConfiguration(FailingConfig.class).run(loaded -> {
|
||||||
|
assertThat(loaded).hasFailed();
|
||||||
|
});
|
||||||
|
assertThat(System.getProperties().containsKey(key)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithSystemPropertiesShouldRestoreOriginalProperties()
|
||||||
|
throws Exception {
|
||||||
|
String key = "test." + UUID.randomUUID().toString();
|
||||||
|
System.setProperty(key, "value");
|
||||||
|
try {
|
||||||
|
assertThat(System.getProperties().getProperty(key)).isEqualTo("value");
|
||||||
|
get().withSystemProperties(key + "=newValue").run(loaded -> {
|
||||||
|
assertThat(System.getProperties()).containsEntry(key, "newValue");
|
||||||
|
});
|
||||||
|
assertThat(System.getProperties().getProperty(key)).isEqualTo("value");
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
System.clearProperty(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithSystemPropertiesWhenValueIsNullShouldRemoveProperty()
|
||||||
|
throws Exception {
|
||||||
|
String key = "test." + UUID.randomUUID().toString();
|
||||||
|
System.setProperty(key, "value");
|
||||||
|
try {
|
||||||
|
assertThat(System.getProperties().getProperty(key)).isEqualTo("value");
|
||||||
|
get().withSystemProperty(key, null).run(loaded -> {
|
||||||
|
assertThat(System.getProperties()).doesNotContainKey(key);
|
||||||
|
});
|
||||||
|
assertThat(System.getProperties().getProperty(key)).isEqualTo("value");
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
System.clearProperty(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithMultiplePropertyValuesShouldAllAllValues() throws Exception {
|
||||||
|
get().withPropertyValues("test.foo=1").withPropertyValues("test.bar=2")
|
||||||
|
.run(loaded -> {
|
||||||
|
Environment environment = loaded.getEnvironment();
|
||||||
|
assertThat(environment.getProperty("test.foo")).isEqualTo("1");
|
||||||
|
assertThat(environment.getProperty("test.bar")).isEqualTo("2");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithPropertyValuesWhenHasExistingShouldReplaceValue()
|
||||||
|
throws Exception {
|
||||||
|
get().withPropertyValues("test.foo=1").withPropertyValues("test.foo=2")
|
||||||
|
.run(loaded -> {
|
||||||
|
Environment environment = loaded.getEnvironment();
|
||||||
|
assertThat(environment.getProperty("test.foo")).isEqualTo("2");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithConfigurationsShouldRegisterConfigurations() throws Exception {
|
||||||
|
get().withUserConfiguration(FooConfig.class)
|
||||||
|
.run((loaded) -> assertThat(loaded).hasBean("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithMultipleConfigurationsShouldRegisterAllConfigurations()
|
||||||
|
throws Exception {
|
||||||
|
get().withUserConfiguration(FooConfig.class)
|
||||||
|
.withConfiguration(UserConfigurations.of(BarConfig.class))
|
||||||
|
.run((loaded) -> assertThat(loaded).hasBean("foo").hasBean("bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithFailedContextShouldReturnFailedAssertableContext()
|
||||||
|
throws Exception {
|
||||||
|
get().withUserConfiguration(FailingConfig.class)
|
||||||
|
.run((loaded) -> assertThat(loaded).hasFailed());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithClassLoaderShouldSetClassLoader() throws Exception {
|
||||||
|
get().withClassLoader(
|
||||||
|
new HidePackagesClassLoader(Gson.class.getPackage().getName()))
|
||||||
|
.run((loaded) -> {
|
||||||
|
try {
|
||||||
|
ClassUtils.forName(Gson.class.getName(), loaded.getClassLoader());
|
||||||
|
fail("Should have thrown a ClassNotFoundException");
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T get();
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class FailingConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String foo() {
|
||||||
|
throw new IllegalStateException("Failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class FooConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String foo() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class BarConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String bar() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* 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.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ApplicationContextAssert}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class ApplicationContextAssertTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
private StaticApplicationContext context = new StaticApplicationContext();
|
||||||
|
|
||||||
|
private RuntimeException failure = new RuntimeException();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createWhenApplicationContextIsNullShouldThrowException()
|
||||||
|
throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("ApplicationContext must not be null");
|
||||||
|
new ApplicationContextAssert<>(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createWhenHasApplicationContextShouldSetActual() throws Exception {
|
||||||
|
assertThat(getAssert(this.context).getSourceApplicationContext())
|
||||||
|
.isSameAs(this.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createWhenHasExceptionShouldSetFailure() throws Exception {
|
||||||
|
assertThat(getAssert(this.failure)).getFailure().isSameAs(this.failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasBeanWhenHasBeanShouldPass() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).hasBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasBeanWhenHasNoBeanShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("no such bean");
|
||||||
|
assertThat(getAssert(this.context)).hasBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasBeanWhenNotStartedShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).hasBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasSingleBeanWhenHasSingleBeanShouldPass() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).hasSingleBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasSingleBeanWhenHasNoBeansShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("no beans of that type");
|
||||||
|
assertThat(getAssert(this.context)).hasSingleBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasSingleBeanWhenHasMultipleShouldFail() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
this.context.registerSingleton("bar", Foo.class);
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("but found:");
|
||||||
|
assertThat(getAssert(this.context)).hasSingleBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasSingleBeanWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).hasSingleBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfTypeWhenHasNoBeanOfTypeShouldPass() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).doesNotHaveBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfTypeWhenHasBeanOfTypeShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("but found");
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).doesNotHaveBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfTypeWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).doesNotHaveBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfNameWhenHasNoBeanOfTypeShouldPass() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).doesNotHaveBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfNameWhenHasBeanOfTypeShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("but found");
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).doesNotHaveBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doesNotHaveBeanOfNameWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).doesNotHaveBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanNamesWhenHasNamesShouldReturnNamesAssert() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
this.context.registerSingleton("bar", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).getBeanNames(Foo.class).containsOnly("foo",
|
||||||
|
"bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanNamesWhenHasNoNamesShouldReturnEmptyAssert() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).getBeanNames(Foo.class).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanNamesWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).doesNotHaveBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfTypeWhenHasBeanShouldReturnBeanAssert() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).getBean(Foo.class).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfTypeWhenHasNoBeanShouldReturnNullAssert() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).getBean(Foo.class).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfTypeWhenHasMultipleBeansShouldFail() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
this.context.registerSingleton("bar", Foo.class);
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("but found");
|
||||||
|
assertThat(getAssert(this.context)).getBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfTypeWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).getBean(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameWhenHasBeanShouldReturnBeanAssert() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).getBean("foo").isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameWhenHasNoBeanOfNameShouldReturnNullAssert()
|
||||||
|
throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).getBean("foo").isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).getBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameAndTypeWhenHasBeanShouldReturnBeanAssert() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).getBean("foo", Foo.class).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameAndTypeWhenHasNoBeanOfNameShouldReturnNullAssert()
|
||||||
|
throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).getBean("foo", Foo.class).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameAndTypeWhenHasNoBeanOfNameButDifferentTypeShouldFail()
|
||||||
|
throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("of type");
|
||||||
|
assertThat(getAssert(this.context)).getBean("foo", String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeanOfNameAndTypeWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).getBean("foo", Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeansWhenHasBeansShouldReturnMapAssert() throws Exception {
|
||||||
|
this.context.registerSingleton("foo", Foo.class);
|
||||||
|
this.context.registerSingleton("bar", Foo.class);
|
||||||
|
assertThat(getAssert(this.context)).getBeans(Foo.class).hasSize(2)
|
||||||
|
.containsKeys("foo", "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeansWhenHasNoBeansShouldReturnEmptyMapAssert() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).getBeans(Foo.class).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBeansWhenFailedToStartShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
assertThat(getAssert(this.failure)).getBeans(Foo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFailureWhenFailedShouldReturnFailure() throws Exception {
|
||||||
|
assertThat(getAssert(this.failure)).getFailure().isSameAs(this.failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFailureWhenDidNotFailShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("context started");
|
||||||
|
assertThat(getAssert(this.context)).getFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasFailedWhenFailedShouldPass() throws Exception {
|
||||||
|
assertThat(getAssert(this.failure)).hasFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasFailedWhenNotFailedShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("to have failed");
|
||||||
|
assertThat(getAssert(this.context)).hasFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasNotFailedWhenFailedShouldFail() throws Exception {
|
||||||
|
this.thrown.expect(AssertionError.class);
|
||||||
|
this.thrown.expectMessage("to have not failed");
|
||||||
|
assertThat(getAssert(this.failure)).hasNotFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasNotFailedWhenNotFailedShouldPass() throws Exception {
|
||||||
|
assertThat(getAssert(this.context)).hasNotFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AssertableApplicationContext getAssert(
|
||||||
|
ConfigurableApplicationContext applicationContext) {
|
||||||
|
return AssertableApplicationContext.get(() -> applicationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AssertableApplicationContext getAssert(RuntimeException failure) {
|
||||||
|
return AssertableApplicationContext.get(() -> {
|
||||||
|
throw failure;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Foo {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AssertProviderApplicationContext} and
|
||||||
|
* {@link AssertProviderApplicationContextInvocationHandler}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class AssertProviderApplicationContextTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ConfigurableApplicationContext mockContext;
|
||||||
|
|
||||||
|
private RuntimeException startupFailure;
|
||||||
|
|
||||||
|
private Supplier<ApplicationContext> mockContextSupplier;
|
||||||
|
|
||||||
|
private Supplier<ApplicationContext> startupFailureSupplier;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
this.startupFailure = new RuntimeException();
|
||||||
|
this.mockContextSupplier = () -> this.mockContext;
|
||||||
|
this.startupFailureSupplier = () -> {
|
||||||
|
throw this.startupFailure;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenTypeIsNullShouldThrowExecption() throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Type must not be null");
|
||||||
|
AssertProviderApplicationContext.get(null, ApplicationContext.class,
|
||||||
|
this.mockContextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenTypeIsClassShouldThrowException() throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Type must not be null");
|
||||||
|
AssertProviderApplicationContext.get(null, ApplicationContext.class,
|
||||||
|
this.mockContextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenContextTypeIsNullShouldThrowException() throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Type must be an interface");
|
||||||
|
AssertProviderApplicationContext.get(
|
||||||
|
TestAssertProviderApplicationContextClass.class, ApplicationContext.class,
|
||||||
|
this.mockContextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenContextTypeIsClassShouldThrowException() throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("ContextType must not be null");
|
||||||
|
AssertProviderApplicationContext.get(TestAssertProviderApplicationContext.class,
|
||||||
|
null, this.mockContextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenSupplierIsNullShouldThrowException() throws Exception {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("ContextType must be an interface");
|
||||||
|
AssertProviderApplicationContext.get(TestAssertProviderApplicationContext.class,
|
||||||
|
StaticApplicationContext.class, this.mockContextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenContextStartsShouldReturnProxyThatCallsRealMethods()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
assertThat((Object) context).isNotNull();
|
||||||
|
context.getBean("foo");
|
||||||
|
verify(this.mockContext).getBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWhenContextFailsShouldReturnProxyThatThrowsExceptions()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
assertThat((Object) context).isNotNull();
|
||||||
|
expectStartupFailure();
|
||||||
|
context.getBean("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSourceContextWhenContextStartsShouldReturnSourceContext()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
assertThat(context.getSourceApplicationContext()).isSameAs(this.mockContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSourceContextWhenContextFailsShouldThrowException() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
expectStartupFailure();
|
||||||
|
context.getSourceApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSourceContextOfTypeWhenContextStartsShouldReturnSourceContext()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
assertThat(context.getSourceApplicationContext(ApplicationContext.class))
|
||||||
|
.isSameAs(this.mockContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSourceContextOfTypeWhenContextFailsToStartShouldThrowException()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
expectStartupFailure();
|
||||||
|
context.getSourceApplicationContext(ApplicationContext.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStartupFailureWhenContextStartsShouldReturnNull() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
assertThat(context.getStartupFailure()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStartupFailureWhenContextFailsToStartShouldReturnException()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
assertThat(context.getStartupFailure()).isEqualTo(this.startupFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void assertThatWhenContextStartsShouldReturnAssertions() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
ApplicationContextAssert<ApplicationContext> contextAssert = assertThat(context);
|
||||||
|
assertThat(contextAssert.getApplicationContext()).isSameAs(context);
|
||||||
|
assertThat(contextAssert.getStartupFailure()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void assertThatWhenContextFailsShouldReturnAssertions() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
ApplicationContextAssert<ApplicationContext> contextAssert = assertThat(context);
|
||||||
|
assertThat(contextAssert.getApplicationContext()).isSameAs(context);
|
||||||
|
assertThat(contextAssert.getStartupFailure()).isSameAs(this.startupFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringWhenContextStartsShouldReturnSimpleString() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
assertThat(context.toString())
|
||||||
|
.startsWith(
|
||||||
|
"Started application org.springframework.context.ConfigurableApplicationContext$MockitoMock")
|
||||||
|
.endsWith("[id=<null>,applicationName=<null>,beanDefinitionCount=0]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringWhenContextFailsToStartShouldReturnSimpleString()
|
||||||
|
throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.startupFailureSupplier);
|
||||||
|
assertThat(context.toString()).isEqualTo("Unstarted application context "
|
||||||
|
+ "org.springframework.context.ApplicationContext"
|
||||||
|
+ "[startupFailure=java.lang.RuntimeException]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void closeShouldCloseContext() throws Exception {
|
||||||
|
AssertProviderApplicationContext<ApplicationContext> context = get(
|
||||||
|
this.mockContextSupplier);
|
||||||
|
context.close();
|
||||||
|
verify(this.mockContext).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectStartupFailure() {
|
||||||
|
this.thrown.expect(IllegalStateException.class);
|
||||||
|
this.thrown.expectMessage("failed to start");
|
||||||
|
this.thrown.expectCause(equalTo(this.startupFailure));
|
||||||
|
}
|
||||||
|
|
||||||
|
private AssertProviderApplicationContext<ApplicationContext> get(
|
||||||
|
Supplier<ApplicationContext> contextSupplier) {
|
||||||
|
return AssertProviderApplicationContext.get(
|
||||||
|
TestAssertProviderApplicationContext.class, ApplicationContext.class,
|
||||||
|
contextSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface TestAssertProviderApplicationContext
|
||||||
|
extends AssertProviderApplicationContext<ApplicationContext> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract static class TestAssertProviderApplicationContextClass
|
||||||
|
implements TestAssertProviderApplicationContext {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AssertableApplicationContext}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @see AssertProviderApplicationContextTests
|
||||||
|
*/
|
||||||
|
public class AssertableApplicationContextTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getShouldReturnProxy() {
|
||||||
|
AssertableApplicationContext context = AssertableApplicationContext
|
||||||
|
.get(() -> mock(ConfigurableApplicationContext.class));
|
||||||
|
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AssertableReactiveWebApplicationContext}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @see AssertProviderApplicationContextTests
|
||||||
|
*/
|
||||||
|
public class AssertableReactiveWebApplicationContextTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getShouldReturnProxy() {
|
||||||
|
AssertableReactiveWebApplicationContext context = AssertableReactiveWebApplicationContext
|
||||||
|
.get(() -> mock(ConfigurableReactiveWebApplicationContext.class));
|
||||||
|
assertThat(context).isInstanceOf(ConfigurableReactiveWebApplicationContext.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,258 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.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.context.annotation.AnnotationConfigApplicationContext;
|
|
||||||
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 StandardContextLoader}.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
*/
|
|
||||||
public class StandardContextLoaderTests {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final ExpectedException thrown = ExpectedException.none();
|
|
||||||
|
|
||||||
private final StandardContextLoader contextLoader = new StandardContextLoader(
|
|
||||||
AnnotationConfigApplicationContext::new);
|
|
||||||
|
|
||||||
@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 autoConfigureFirstWithSeveralConfigsIsAppliedProperly() {
|
|
||||||
this.contextLoader.autoConfig(ConfigA.class, ConfigB.class)
|
|
||||||
.autoConfigFirst(AutoConfigA.class, AutoConfigB.class).load(context -> {
|
|
||||||
assertThat(context.getBean("a")).isEqualTo("a");
|
|
||||||
assertThat(context.getBean("b")).isEqualTo(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void assertionErrorsAreAvailableAsIs() {
|
|
||||||
try {
|
|
||||||
this.contextLoader.load(context -> {
|
|
||||||
fail("This is expected");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (AssertionError ex) {
|
|
||||||
assertThat(ex.getMessage()).isEqualTo("This is 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link WebApplicationContextTester}.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class WebApplicationContextTesterTests extends
|
||||||
|
AbstractApplicationContextTesterTests<WebApplicationContextTester, ConfigurableWebApplicationContext, AssertableWebApplicationContext> {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextShouldHaveMockServletContext() throws Exception {
|
||||||
|
get().run((loaded) -> assertThat(loaded.getServletContext())
|
||||||
|
.isInstanceOf(MockServletContext.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WebApplicationContextTester get() {
|
||||||
|
return new WebApplicationContextTester();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue