001/* 002 * Copyright 2002-2019 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 * https://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.test.context.support; 018 019import java.lang.reflect.Constructor; 020import java.lang.reflect.Executable; 021 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024 025import org.springframework.beans.factory.annotation.Autowired; 026import org.springframework.core.SpringProperties; 027import org.springframework.core.annotation.AnnotatedElementUtils; 028import org.springframework.test.context.TestConstructor; 029import org.springframework.test.context.TestConstructor.AutowireMode; 030 031/** 032 * Utility methods for working with {@link TestConstructor @TestConstructor}. 033 * 034 * <p>Primarily intended for use within the framework. 035 * 036 * @author Sam Brannen 037 * @since 5.2 038 * @see TestConstructor 039 */ 040public abstract class TestConstructorUtils { 041 042 private static final Log logger = LogFactory.getLog(TestConstructorUtils.class); 043 044 045 private TestConstructorUtils() { 046 } 047 048 /** 049 * Determine if the supplied executable for the given test class is an 050 * autowirable constructor. 051 * 052 * <p>This method delegates to {@link #isAutowirableConstructor(Constructor, Class)} 053 * if the executable is a constructor. 054 * 055 * @param executable an executable for the test class 056 * @param testClass the test class 057 * @return {@code true} if the executable is an autowirable constructor 058 * @see #isAutowirableConstructor(Constructor, Class) 059 */ 060 public static boolean isAutowirableConstructor(Executable executable, Class<?> testClass) { 061 return (executable instanceof Constructor && 062 isAutowirableConstructor((Constructor<?>) executable, testClass)); 063 } 064 065 /** 066 * Determine if the supplied constructor for the given test class is 067 * autowirable. 068 * 069 * <p>A constructor is considered to be autowirable if one of the following 070 * conditions is {@code true}. 071 * 072 * <ol> 073 * <li>The constructor is annotated with {@link Autowired @Autowired}.</li> 074 * <li>{@link TestConstructor @TestConstructor} is <em>present</em> or 075 * <em>meta-present</em> on the test class with 076 * {@link TestConstructor#autowireMode() autowireMode} set to 077 * {@link AutowireMode#ALL ALL}.</li> 078 * <li>The default <em>test constructor autowire mode</em> has been changed 079 * to {@code ALL} (see 080 * {@link TestConstructor#TEST_CONSTRUCTOR_AUTOWIRE_MODE_PROPERTY_NAME}).</li> 081 * </ol> 082 * 083 * @param constructor a constructor for the test class 084 * @param testClass the test class 085 * @return {@code true} if the constructor is autowirable 086 * @see #isAutowirableConstructor(Executable, Class) 087 */ 088 public static boolean isAutowirableConstructor(Constructor<?> constructor, Class<?> testClass) { 089 // Is the constructor annotated with @Autowired? 090 if (AnnotatedElementUtils.hasAnnotation(constructor, Autowired.class)) { 091 return true; 092 } 093 094 AutowireMode autowireMode = null; 095 096 // Is the test class annotated with @TestConstructor? 097 TestConstructor testConstructor = AnnotatedElementUtils.findMergedAnnotation(testClass, TestConstructor.class); 098 if (testConstructor != null) { 099 autowireMode = testConstructor.autowireMode(); 100 } 101 else { 102 // Custom global default? 103 String value = SpringProperties.getProperty(TestConstructor.TEST_CONSTRUCTOR_AUTOWIRE_MODE_PROPERTY_NAME); 104 if (value != null) { 105 try { 106 autowireMode = AutowireMode.valueOf(value.trim().toUpperCase()); 107 } 108 catch (Exception ex) { 109 if (logger.isDebugEnabled()) { 110 logger.debug(String.format("Failed to parse autowire mode '%s' for property '%s': %s", value, 111 TestConstructor.TEST_CONSTRUCTOR_AUTOWIRE_MODE_PROPERTY_NAME, ex.getMessage())); 112 } 113 } 114 } 115 } 116 117 return (autowireMode == AutowireMode.ALL); 118 } 119 120}