|
|
|
|
@@ -19,9 +19,12 @@ package org.springframework.boot.test.context.runner;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
|
|
|
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
|
|
|
|
import org.springframework.beans.factory.support.BeanNameGenerator;
|
|
|
|
|
import org.springframework.boot.context.annotation.Configurations;
|
|
|
|
|
import org.springframework.boot.context.annotation.UserConfigurations;
|
|
|
|
|
@@ -112,6 +115,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
|
|
|
|
|
private final ApplicationContext parent;
|
|
|
|
|
|
|
|
|
|
private final List<BeanRegistration<?>> beanRegistrations;
|
|
|
|
|
|
|
|
|
|
private final List<Configurations> configurations;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -120,7 +125,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
*/
|
|
|
|
|
protected AbstractApplicationContextRunner(Supplier<C> contextFactory) {
|
|
|
|
|
this(contextFactory, Collections.emptyList(), TestPropertyValues.empty(),
|
|
|
|
|
TestPropertyValues.empty(), null, null, Collections.emptyList());
|
|
|
|
|
TestPropertyValues.empty(), null, null, Collections.emptyList(),
|
|
|
|
|
Collections.emptyList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -131,12 +137,14 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
* @param systemProperties the system properties
|
|
|
|
|
* @param classLoader the class loader
|
|
|
|
|
* @param parent the parent
|
|
|
|
|
* @param beanRegistrations the bean registrations
|
|
|
|
|
* @param configurations the configuration
|
|
|
|
|
*/
|
|
|
|
|
protected AbstractApplicationContextRunner(Supplier<C> contextFactory,
|
|
|
|
|
List<ApplicationContextInitializer<? super C>> initializers,
|
|
|
|
|
TestPropertyValues environmentProperties, TestPropertyValues systemProperties,
|
|
|
|
|
ClassLoader classLoader, ApplicationContext parent,
|
|
|
|
|
List<BeanRegistration<?>> beanRegistrations,
|
|
|
|
|
List<Configurations> configurations) {
|
|
|
|
|
Assert.notNull(contextFactory, "ContextFactory must not be null");
|
|
|
|
|
Assert.notNull(environmentProperties, "EnvironmentProperties must not be null");
|
|
|
|
|
@@ -149,6 +157,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
this.systemProperties = systemProperties;
|
|
|
|
|
this.classLoader = classLoader;
|
|
|
|
|
this.parent = parent;
|
|
|
|
|
this.beanRegistrations = Collections.unmodifiableList(beanRegistrations);
|
|
|
|
|
this.configurations = Collections.unmodifiableList(configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -162,7 +171,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
Assert.notNull(initializer, "Initializer must not be null");
|
|
|
|
|
return newInstance(this.contextFactory, add(this.initializers, initializer),
|
|
|
|
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
|
|
|
|
this.parent, this.configurations);
|
|
|
|
|
this.parent, this.beanRegistrations, this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -178,7 +187,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
public SELF withPropertyValues(String... pairs) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties.and(pairs), this.systemProperties,
|
|
|
|
|
this.classLoader, this.parent, this.configurations);
|
|
|
|
|
this.classLoader, this.parent, this.beanRegistrations,
|
|
|
|
|
this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -194,7 +204,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
public SELF withSystemProperties(String... pairs) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties.and(pairs),
|
|
|
|
|
this.classLoader, this.parent, this.configurations);
|
|
|
|
|
this.classLoader, this.parent, this.beanRegistrations,
|
|
|
|
|
this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -207,7 +218,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
public SELF withClassLoader(ClassLoader classLoader) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties, classLoader,
|
|
|
|
|
this.parent, this.configurations);
|
|
|
|
|
this.parent, this.beanRegistrations, this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -219,7 +230,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
public SELF withParent(ApplicationContext parent) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
|
|
|
|
parent, this.configurations);
|
|
|
|
|
parent, this.beanRegistrations, this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -229,13 +240,37 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
* <p>
|
|
|
|
|
* Such beans are registered after regular {@linkplain #withUserConfiguration(Class[])
|
|
|
|
|
* user configurations} in the order of registration.
|
|
|
|
|
* @param beanType the type of the bean
|
|
|
|
|
* @param beanDefinition a supplier for the bean
|
|
|
|
|
* @param type the type of the bean
|
|
|
|
|
* @param constructorArgs custom argument values to be fed into Spring's constructor
|
|
|
|
|
* resolution algorithm, resolving either all arguments or just specific ones, with
|
|
|
|
|
* the rest to be resolved through regular autowiring (may be {@code null} or empty)
|
|
|
|
|
* @param <T> the type of the bean
|
|
|
|
|
* @return a new instance with the updated bean
|
|
|
|
|
*/
|
|
|
|
|
public <T> SELF withBean(Class<T> beanType, Supplier<T> beanDefinition) {
|
|
|
|
|
return withBean(null, beanType, beanDefinition);
|
|
|
|
|
public <T> SELF withBean(Class<T> type, Object... constructorArgs) {
|
|
|
|
|
return withBean(null, type, constructorArgs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register the specified user bean with the {@link ApplicationContext}.
|
|
|
|
|
* <p>
|
|
|
|
|
* Such beans are registered after regular {@linkplain #withUserConfiguration(Class[])
|
|
|
|
|
* user configurations} in the order of registration.
|
|
|
|
|
* @param name the bean name or {@code null} to use a generated name
|
|
|
|
|
* @param type the type of the bean
|
|
|
|
|
* @param constructorArgs custom argument values to be fed into Spring's constructor
|
|
|
|
|
* resolution algorithm, resolving either all arguments or just specific ones, with
|
|
|
|
|
* the rest to be resolved through regular autowiring (may be {@code null} or empty)
|
|
|
|
|
* @param <T> the type of the bean
|
|
|
|
|
* @return a new instance with the updated bean
|
|
|
|
|
*/
|
|
|
|
|
public <T> SELF withBean(String name, Class<T> type, Object... constructorArgs) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
|
|
|
|
this.parent,
|
|
|
|
|
add(this.beanRegistrations,
|
|
|
|
|
new BeanRegistration<>(name, type, constructorArgs)),
|
|
|
|
|
this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -245,59 +280,41 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
* <p>
|
|
|
|
|
* Such beans are registered after regular {@linkplain #withUserConfiguration(Class[])
|
|
|
|
|
* user configurations} in the order of registration.
|
|
|
|
|
* @param beanType the type of the bean
|
|
|
|
|
* @param beanDefinition a function that accepts the context and return the bean
|
|
|
|
|
* @param type the type of the bean
|
|
|
|
|
* @param supplier a supplier for the bean
|
|
|
|
|
* @param customizers one or more callbacks for customizing the factory's
|
|
|
|
|
* {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
|
|
|
|
|
* @param <T> the type of the bean
|
|
|
|
|
* @return a new instance with the updated bean
|
|
|
|
|
*/
|
|
|
|
|
public <T> SELF withBean(Class<T> beanType, Function<? super C, T> beanDefinition) {
|
|
|
|
|
return withBean(null, beanType, beanDefinition);
|
|
|
|
|
public <T> SELF withBean(Class<T> type, Supplier<T> supplier,
|
|
|
|
|
BeanDefinitionCustomizer... customizers) {
|
|
|
|
|
return withBean(null, type, supplier, customizers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register the specified user bean with the {@link ApplicationContext}. If no bean
|
|
|
|
|
* name is provided, a default one is generated from the configured
|
|
|
|
|
* {@link BeanNameGenerator} on the underlying context.
|
|
|
|
|
* Register the specified user bean with the {@link ApplicationContext}. The bean name
|
|
|
|
|
* is generated from the configured {@link BeanNameGenerator} on the underlying
|
|
|
|
|
* context.
|
|
|
|
|
* <p>
|
|
|
|
|
* Such beans are registered after regular {@linkplain #withUserConfiguration(Class[])
|
|
|
|
|
* user configurations} in the order of registration.
|
|
|
|
|
* @param beanName the name of the bean (may be {@code null})
|
|
|
|
|
* @param beanType the type of the bean
|
|
|
|
|
* @param beanDefinition a supplier for the bean
|
|
|
|
|
* @param name the bean name or {@code null} to use a generated name
|
|
|
|
|
* @param type the type of the bean
|
|
|
|
|
* @param supplier a supplier for the bean
|
|
|
|
|
* @param customizers one or more callbacks for customizing the factory's
|
|
|
|
|
* {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
|
|
|
|
|
* @param <T> the type of the bean
|
|
|
|
|
* @return a new instance with the updated bean
|
|
|
|
|
*/
|
|
|
|
|
public <T> SELF withBean(String beanName, Class<T> beanType,
|
|
|
|
|
Supplier<T> beanDefinition) {
|
|
|
|
|
return withBean(beanName, beanType, (context) -> beanDefinition.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register the specified user bean with the {@link ApplicationContext}. If no bean
|
|
|
|
|
* name is provided, a default one is generated from the configured
|
|
|
|
|
* {@link BeanNameGenerator} on the underlying context.
|
|
|
|
|
* <p>
|
|
|
|
|
* Such beans are registered after regular {@linkplain #withUserConfiguration(Class[])
|
|
|
|
|
* user configurations} in the order of registration.
|
|
|
|
|
* @param beanName the name of the bean (may be {@code null})
|
|
|
|
|
* @param beanType the type of the bean
|
|
|
|
|
* @param beanDefinition a function that accepts the context and return the bean
|
|
|
|
|
* @param <T> the type of the bean
|
|
|
|
|
* @return a new instance with the updated bean
|
|
|
|
|
*/
|
|
|
|
|
public <T> SELF withBean(String beanName, Class<T> beanType,
|
|
|
|
|
Function<? super C, T> beanDefinition) {
|
|
|
|
|
return withInitializer(
|
|
|
|
|
beanDefinitionRegistrar(beanName, beanType, beanDefinition));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private <T> ApplicationContextInitializer<? super C> beanDefinitionRegistrar(
|
|
|
|
|
String beanName, Class<T> beanType, Function<? super C, T> beanDefinition) {
|
|
|
|
|
return (context) -> {
|
|
|
|
|
Assert.isInstanceOf(GenericApplicationContext.class, context);
|
|
|
|
|
((GenericApplicationContext) context).registerBean(beanName, beanType,
|
|
|
|
|
() -> beanDefinition.apply(context));
|
|
|
|
|
};
|
|
|
|
|
public <T> SELF withBean(String name, Class<T> type, Supplier<T> supplier,
|
|
|
|
|
BeanDefinitionCustomizer... customizers) {
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
|
|
|
|
this.parent,
|
|
|
|
|
add(this.beanRegistrations,
|
|
|
|
|
new BeanRegistration<>(name, type, supplier, customizers)),
|
|
|
|
|
this.configurations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -319,7 +336,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
Assert.notNull(configurations, "Configurations must not be null");
|
|
|
|
|
return newInstance(this.contextFactory, this.initializers,
|
|
|
|
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
|
|
|
|
this.parent, add(this.configurations, configurations));
|
|
|
|
|
this.parent, this.beanRegistrations,
|
|
|
|
|
add(this.configurations, configurations));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -342,6 +360,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
List<ApplicationContextInitializer<? super C>> initializers,
|
|
|
|
|
TestPropertyValues environmentProperties, TestPropertyValues systemProperties,
|
|
|
|
|
ClassLoader classLoader, ApplicationContext parent,
|
|
|
|
|
List<BeanRegistration<?>> beanRegistrations,
|
|
|
|
|
List<Configurations> configurations);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -416,6 +435,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
if (classes.length > 0) {
|
|
|
|
|
((AnnotationConfigRegistry) context).register(classes);
|
|
|
|
|
}
|
|
|
|
|
this.beanRegistrations.forEach((registration) -> registration.apply(context));
|
|
|
|
|
this.initializers.forEach((initializer) -> initializer.initialize(context));
|
|
|
|
|
context.refresh();
|
|
|
|
|
}
|
|
|
|
|
@@ -434,4 +454,31 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
|
|
|
|
throw (E) e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A Bean registration to be applied when the context loaded.
|
|
|
|
|
*
|
|
|
|
|
* @param <T> the bean type
|
|
|
|
|
*/
|
|
|
|
|
protected final class BeanRegistration<T> {
|
|
|
|
|
|
|
|
|
|
Consumer<GenericApplicationContext> registrar;
|
|
|
|
|
|
|
|
|
|
public BeanRegistration(String name, Class<T> type, Object... constructorArgs) {
|
|
|
|
|
this.registrar = (context) -> context.registerBean(name, type,
|
|
|
|
|
constructorArgs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public BeanRegistration(String name, Class<T> type, Supplier<T> supplier,
|
|
|
|
|
BeanDefinitionCustomizer... customizers) {
|
|
|
|
|
this.registrar = (context) -> context.registerBean(name, type, supplier,
|
|
|
|
|
customizers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void apply(ConfigurableApplicationContext context) {
|
|
|
|
|
Assert.isInstanceOf(GenericApplicationContext.class, context);
|
|
|
|
|
this.registrar.accept(((GenericApplicationContext) context));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|