/* * Copyright 2012-2016 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.diagnostics.analyzer; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.diagnostics.analyzer.nounique.TestBean; import org.springframework.boot.diagnostics.analyzer.nounique.TestBeanConsumer; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import static org.assertj.core.api.Assertions.assertThat; /** * Tests for {@link NoUniqueBeanDefinitionFailureAnalyzer}. * * @author Andy Wilkinson */ public class NoUniqueBeanDefinitionFailureAnalyzerTests { private final NoUniqueBeanDefinitionFailureAnalyzer analyzer = new NoUniqueBeanDefinitionFailureAnalyzer(); @Test public void failureAnalysisForFieldConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(FieldConsumer.class)); assertThat(failureAnalysis.getDescription()) .startsWith("Field testBean in " + FieldConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } @Test public void failureAnalysisForMethodConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(MethodConsumer.class)); assertThat(failureAnalysis.getDescription()).startsWith( "Parameter 0 of method consumer in " + MethodConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } @Test public void failureAnalysisForConstructorConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(ConstructorConsumer.class)); assertThat(failureAnalysis.getDescription()).startsWith( "Parameter 0 of constructor in " + ConstructorConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } @Test public void failureAnalysisForObjectProviderMethodConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(ObjectProviderMethodConsumer.class)); assertThat(failureAnalysis.getDescription()).startsWith( "Method consumer in " + ObjectProviderMethodConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } @Test public void failureAnalysisForXmlConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(XmlConsumer.class)); assertThat(failureAnalysis.getDescription()).startsWith( "Parameter 0 of constructor in " + TestBeanConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } @Test public void failureAnalysisForObjectProviderConstructorConsumer() { FailureAnalysis failureAnalysis = analyzeFailure( createFailure(ObjectProviderConstructorConsumer.class)); assertThat(failureAnalysis.getDescription()).startsWith( "Constructor in " + ObjectProviderConstructorConsumer.class.getName() + " required a single bean, but 6 were found:"); assertFoundBeans(failureAnalysis); } private BeanCreationException createFailure(Class<?> consumer) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(DuplicateBeansProducer.class, consumer); context.setParent(new AnnotationConfigApplicationContext(ParentProducer.class)); try { context.refresh(); return null; } catch (BeanCreationException ex) { this.analyzer.setBeanFactory(context.getBeanFactory()); return ex; } finally { context.close(); } } private FailureAnalysis analyzeFailure(BeanCreationException failure) { return this.analyzer.analyze(failure); } private void assertFoundBeans(FailureAnalysis analysis) { assertThat(analysis.getDescription()) .contains("beanOne: defined by method 'beanOne' in " + DuplicateBeansProducer.class.getName()); assertThat(analysis.getDescription()) .contains("beanTwo: defined by method 'beanTwo' in " + DuplicateBeansProducer.class.getName()); assertThat(analysis.getDescription()) .contains("beanThree: defined by method 'beanThree' in " + ParentProducer.class.getName()); assertThat(analysis.getDescription()).contains("barTestBean"); assertThat(analysis.getDescription()).contains("fooTestBean"); assertThat(analysis.getDescription()).contains("xmlTestBean"); } @Configuration @ComponentScan(basePackageClasses = TestBean.class) @ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/producer.xml") static class DuplicateBeansProducer { @Bean TestBean beanOne() { return new TestBean(); } @Bean TestBean beanTwo() { return new TestBean(); } } static class ParentProducer { @Bean TestBean beanThree() { return new TestBean(); } } @Configuration static class FieldConsumer { @SuppressWarnings("unused") @Autowired private TestBean testBean; } @Configuration static class ObjectProviderConstructorConsumer { ObjectProviderConstructorConsumer(ObjectProvider<TestBean> objectProvider) { objectProvider.getIfAvailable(); } } @Configuration static class ConstructorConsumer { ConstructorConsumer(TestBean testBean) { } } @Configuration static class MethodConsumer { @Bean String consumer(TestBean testBean) { return "foo"; } } @Configuration static class ObjectProviderMethodConsumer { @Bean String consumer(ObjectProvider<TestBean> testBeanProvider) { testBeanProvider.getIfAvailable(); return "foo"; } } @Configuration @ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/consumer.xml") static class XmlConsumer { } }