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-9634
pull/9800/merge
Phillip Webb 7 years ago
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">
* &#064;Test
* public someTest() {
* this.contex.withPropertyValues("spring.foo=biz").run((loaded) -&gt; {
* 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">
* &#064;Test
* public someTest() {
* this.contex.withPropertyValues("spring.foo=fails").run((loaded) -&gt; {
* 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);
}
}

@ -16,24 +16,26 @@
package org.springframework.boot.test.context; package org.springframework.boot.test.context;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ApplicationContext;
/** /**
* Callback interface used in tests to process a running * Callback interface used to process an {@link ApplicationContext} with the ability to
* {@link ConfigurableApplicationContext} with the ability to throw a (checked) exception. * throw a (checked) exception.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Andy Wilkinson * @author Andy Wilkinson
* @param <C> The application context type
* @since 2.0.0 * @since 2.0.0
* @see AbstractApplicationContextTester
*/ */
@FunctionalInterface @FunctionalInterface
public interface ContextConsumer { public interface ContextConsumer<C extends ApplicationContext> {
/** /**
* Performs this operation on the supplied {@code context}. * Performs this operation on the supplied {@code context}.
* @param context the application context to consume * @param context the application context to consume
* @throws Throwable any exception that might occur in assertions * @throws Throwable any exception that might occur in assertions
*/ */
void accept(ConfigurableApplicationContext context) throws Throwable; void accept(C context) throws Throwable;
} }

@ -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 {
*
* &#064;Test
* public someTest() {
* this.contextLoader.config(UserConfig.class).env("spring.foo=biz")
* .load(context -&gt; {
* // 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 {
}
}

@ -16,23 +16,20 @@
package org.springframework.boot.test.context; package org.springframework.boot.test.context;
import java.util.function.Supplier; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/** /**
* A {@link ContextLoader} that simulates a standard, non web environment. * Tests for {@link ApplicationContextTester}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Andy Wilkinson * @author Phillip Webb
* @since 2.0.0
*/ */
public class StandardContextLoader extends public class ApplicationContextTesterTests extends
AbstractContextLoader<AnnotationConfigApplicationContext, StandardContextLoader> { AbstractApplicationContextTesterTests<ApplicationContextTester, ConfigurableApplicationContext, AssertableApplicationContext> {
public StandardContextLoader( @Override
Supplier<AnnotationConfigApplicationContext> contextSupplier) { protected ApplicationContextTester get() {
super(contextSupplier); return new ApplicationContextTester();
} }
} }

@ -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);
}
}

@ -16,25 +16,26 @@
package org.springframework.boot.test.context; package org.springframework.boot.test.context;
import org.junit.Test;
import org.springframework.web.context.ConfigurableWebApplicationContext; import org.springframework.web.context.ConfigurableWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Specialized callback interface used in tests to process a running * Tests for {@link AssertableWebApplicationContext}.
* {@link ConfigurableWebApplicationContext} with the ability to throw a (checked)
* exception.
* *
* @author Stephane Nicoll * @author Phillip Webb
* @see ContextConsumer * @see AssertProviderApplicationContextTests
* @since 2.0.0
*/ */
@FunctionalInterface public class AssertableWebApplicationContextTests {
public interface WebMvcContextConsumer {
/** @Test
* Performs this operation on the supplied {@code context}. public void getShouldReturnProxy() {
* @param context the application context to consume AssertableWebApplicationContext context = AssertableWebApplicationContext
* @throws Throwable any exception that might occur in assertions .get(() -> mock(ConfigurableWebApplicationContext.class));
*/ assertThat(context).isInstanceOf(ConfigurableWebApplicationContext.class);
void accept(ConfigurableWebApplicationContext context) throws Throwable; }
} }

@ -16,24 +16,20 @@
package org.springframework.boot.test.context; 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 ContextLoader} that simulates a {@link GenericReactiveWebApplicationContext} * Tests for {@link ReactiveWebApplicationContextTester}.
* which can be useful to test components that require a reactive web application.
* *
* @author Andy Wilkinson
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @author Phillip Webb
*/ */
public final class ReactiveWebContextLoader extends public class ReactiveWebApplicationContextTesterTests extends
AbstractContextLoader<GenericReactiveWebApplicationContext, ReactiveWebContextLoader> { AbstractApplicationContextTesterTests<ReactiveWebApplicationContextTester, ConfigurableReactiveWebApplicationContext, AssertableReactiveWebApplicationContext> {
ReactiveWebContextLoader( @Override
Supplier<GenericReactiveWebApplicationContext> contextSupplier) { protected ReactiveWebApplicationContextTester get() {
super(contextSupplier); return new ReactiveWebApplicationContextTester();
} }
} }

@ -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…
Cancel
Save