Allow `ApplicationContextRunner` to accept simple bean definitions
This commit adds `withBean` methods to the `ApplicationContextRunner` abstraction so that simple beans can be registered inline. This is a nice alternative for cases where a inner configuration class has to be defined for the purpose of creating a simple bean. Closes gh-16011
This commit is contained in:
parent
7054a33e70
commit
a780875390
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||||
import org.springframework.boot.context.annotation.Configurations;
|
import org.springframework.boot.context.annotation.Configurations;
|
||||||
import org.springframework.boot.context.annotation.UserConfigurations;
|
import org.springframework.boot.context.annotation.UserConfigurations;
|
||||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||||
|
@ -32,6 +33,7 @@ import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.AnnotationConfigRegistry;
|
import org.springframework.context.annotation.AnnotationConfigRegistry;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
@ -156,8 +158,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
||||||
* @param initializer the initializer to add
|
* @param initializer the initializer to add
|
||||||
* @return a new instance with the updated initializers
|
* @return a new instance with the updated initializers
|
||||||
*/
|
*/
|
||||||
public SELF withInitializer(
|
public SELF withInitializer(ApplicationContextInitializer<? super C> initializer) {
|
||||||
ApplicationContextInitializer<? super ConfigurableApplicationContext> initializer) {
|
|
||||||
Assert.notNull(initializer, "Initializer must not be null");
|
Assert.notNull(initializer, "Initializer must not be null");
|
||||||
return newInstance(this.contextFactory, add(this.initializers, initializer),
|
return newInstance(this.contextFactory, add(this.initializers, initializer),
|
||||||
this.environmentProperties, this.systemProperties, this.classLoader,
|
this.environmentProperties, this.systemProperties, this.classLoader,
|
||||||
|
@ -221,6 +222,84 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
|
||||||
parent, this.configurations);
|
parent, this.configurations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 beanType the type of the bean
|
||||||
|
* @param beanDefinition a supplier for the bean
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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(Class<T> beanType, Function<? super C, T> beanDefinition) {
|
||||||
|
return withBean(null, beanType, beanDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 supplier for 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,
|
||||||
|
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));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the specified user configuration classes with the
|
* Register the specified user configuration classes with the
|
||||||
* {@link ApplicationContext}.
|
* {@link ApplicationContext}.
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.springframework.util.ClassUtils;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||||
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract tests for {@link AbstractApplicationContextRunner} implementations.
|
* Abstract tests for {@link AbstractApplicationContextRunner} implementations.
|
||||||
|
@ -136,6 +137,45 @@ public abstract class AbstractApplicationContextRunnerTests<T extends AbstractAp
|
||||||
.run((context) -> assertThat(context).hasBean("foo"));
|
.run((context) -> assertThat(context).hasBean("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithUserNamedBeanShouldRegisterBean() {
|
||||||
|
get().withBean("foo", String.class, () -> "foo")
|
||||||
|
.run((context) -> assertThat(context).hasBean("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithUserBeanShouldRegisterBeanWithDefaultName() {
|
||||||
|
get().withBean(String.class, () -> "foo")
|
||||||
|
.run((context) -> assertThat(context).hasBean("string"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithUserBeanShouldBeRegisteredInOrder() {
|
||||||
|
get().withBean(String.class, () -> "one").withBean(String.class, () -> "two")
|
||||||
|
.withBean(String.class, () -> "three").run((context) -> {
|
||||||
|
assertThat(context).hasBean("string");
|
||||||
|
assertThat(context.getBean("string")).isEqualTo("three");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithConfigurationsAndUserBeanShouldRegisterUserBeanLast() {
|
||||||
|
get().withUserConfiguration(FooConfig.class)
|
||||||
|
.withBean("foo", String.class, () -> "overridden").run((context) -> {
|
||||||
|
assertThat(context).hasBean("foo");
|
||||||
|
assertThat(context.getBean("foo")).isEqualTo("overridden");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithUserBeanShouldHaveAccessToContext() {
|
||||||
|
get().withUserConfiguration(FooConfig.class)
|
||||||
|
.withBean(String.class, (context) -> "Result: " + context.getBean("foo"))
|
||||||
|
.run((context) -> assertThat(context.getBeansOfType(String.class))
|
||||||
|
.containsOnly(entry("foo", "foo"),
|
||||||
|
entry("string", "Result: foo")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runWithMultipleConfigurationsShouldRegisterAllConfigurations() {
|
public void runWithMultipleConfigurationsShouldRegisterAllConfigurations() {
|
||||||
get().withUserConfiguration(FooConfig.class)
|
get().withUserConfiguration(FooConfig.class)
|
||||||
|
|
Loading…
Reference in New Issue