001/*
002 * Copyright 2012-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.test.autoconfigure;
018
019import java.util.LinkedHashSet;
020import java.util.Set;
021
022import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
023import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportMessage;
024import org.springframework.boot.test.context.DefaultTestExecutionListenersPostProcessor;
025import org.springframework.context.ApplicationContext;
026import org.springframework.context.ConfigurableApplicationContext;
027import org.springframework.test.context.TestContext;
028import org.springframework.test.context.TestExecutionListener;
029import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
030
031/**
032 * Alternative {@link DependencyInjectionTestExecutionListener} prints the
033 * {@link ConditionEvaluationReport} when the context cannot be prepared.
034 *
035 * @author Phillip Webb
036 * @since 1.4.1
037 */
038public class SpringBootDependencyInjectionTestExecutionListener
039                extends DependencyInjectionTestExecutionListener {
040
041        @Override
042        public void prepareTestInstance(TestContext testContext) throws Exception {
043                try {
044                        super.prepareTestInstance(testContext);
045                }
046                catch (Exception ex) {
047                        outputConditionEvaluationReport(testContext);
048                        throw ex;
049                }
050        }
051
052        private void outputConditionEvaluationReport(TestContext testContext) {
053                try {
054                        ApplicationContext context = testContext.getApplicationContext();
055                        if (context instanceof ConfigurableApplicationContext) {
056                                ConditionEvaluationReport report = ConditionEvaluationReport
057                                                .get(((ConfigurableApplicationContext) context).getBeanFactory());
058                                System.err.println(new ConditionEvaluationReportMessage(report));
059                        }
060                }
061                catch (Exception ex) {
062                        // Allow original failure to be reported
063                }
064        }
065
066        static class PostProcessor implements DefaultTestExecutionListenersPostProcessor {
067
068                @Override
069                public Set<Class<? extends TestExecutionListener>> postProcessDefaultTestExecutionListeners(
070                                Set<Class<? extends TestExecutionListener>> listeners) {
071                        Set<Class<? extends TestExecutionListener>> updated = new LinkedHashSet<>(
072                                        listeners.size());
073                        for (Class<? extends TestExecutionListener> listener : listeners) {
074                                updated.add(
075                                                listener.equals(DependencyInjectionTestExecutionListener.class)
076                                                                ? SpringBootDependencyInjectionTestExecutionListener.class
077                                                                : listener);
078                        }
079                        return updated;
080                }
081
082        }
083
084}