Fix primary beans with ApplicationContextAssert
Update `ApplicationContextAssert.getBean` so that multiple beans are supported as long as one of them is primary. This aligns better with the way that the standard `ApplicationContext.getBean` method works. Closes gh-14874
This commit is contained in:
parent
06f1a0e6a2
commit
683484e4a8
|
|
@ -32,8 +32,10 @@ import org.assertj.core.error.BasicErrorMessageFactory;
|
|||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -273,17 +275,49 @@ public class ApplicationContextAssert<C extends ApplicationContext>
|
|||
"to contain bean of type:%n <%s>", type));
|
||||
}
|
||||
String[] names = scope.getBeanNamesForType(getApplicationContext(), type);
|
||||
if (names.length > 1) {
|
||||
String name = (names.length > 0) ? getPrimary(names, scope) : null;
|
||||
if (names.length > 1 && name == null) {
|
||||
throwAssertionError(new BasicErrorMessageFactory(
|
||||
"%nExpecting:%n <%s>%nsingle bean of type:%n <%s>%nbut found:%n <%s>",
|
||||
getApplicationContext(), type, names));
|
||||
}
|
||||
T bean = (names.length != 0) ? getApplicationContext().getBean(names[0], type)
|
||||
: null;
|
||||
T bean = (name != null) ? getApplicationContext().getBean(name, type) : null;
|
||||
return Assertions.assertThat(bean).as("Bean of type <%s> from <%s>", type,
|
||||
getApplicationContext());
|
||||
}
|
||||
|
||||
private String getPrimary(String[] names, Scope scope) {
|
||||
if (names.length == 1) {
|
||||
return names[0];
|
||||
}
|
||||
String primary = null;
|
||||
for (String name : names) {
|
||||
if (isPrimary(name, scope)) {
|
||||
if (primary != null) {
|
||||
return null;
|
||||
}
|
||||
primary = name;
|
||||
}
|
||||
}
|
||||
return primary;
|
||||
}
|
||||
|
||||
private boolean isPrimary(String name, Scope scope) {
|
||||
ApplicationContext context = getApplicationContext();
|
||||
while (context != null) {
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
ConfigurableListableBeanFactory factory = ((ConfigurableApplicationContext) context)
|
||||
.getBeanFactory();
|
||||
if (factory.containsBean(name)
|
||||
&& factory.getMergedBeanDefinition(name).isPrimary()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
context = (scope != Scope.NO_ANCESTORS) ? context.getParent() : null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ import org.junit.Test;
|
|||
|
||||
import org.springframework.boot.test.context.assertj.ApplicationContextAssert.Scope;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -244,6 +248,14 @@ public class ApplicationContextAssertTests {
|
|||
.withMessageContaining("but found");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBeanOfTypeWhenHasPrimaryBeanShouldReturnPrimary() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
PrimaryFooConfig.class);
|
||||
assertThat(getAssert(context)).getBean(Foo.class).isInstanceOf(Bar.class);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBeanOfTypeWhenFailedToStartShouldFail() {
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
|
|
@ -423,4 +435,24 @@ public class ApplicationContextAssertTests {
|
|||
|
||||
}
|
||||
|
||||
private static class Bar extends Foo {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class PrimaryFooConfig {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public Bar bar() {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue