KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > test > AbstractDependencyInjectionSpringContextTests


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.test;
18
19 import java.lang.reflect.Field JavaDoc;
20 import java.lang.reflect.Modifier JavaDoc;
21 import java.util.LinkedList JavaDoc;
22
23 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
24 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
25
26 /**
27  * Convenient superclass for tests depending on a Spring context.
28  * The test instance itself is populated by Dependency Injection.
29  *
30  * <p>Really for integration testing, not unit testing.
31  * You should <i>not</i> normally use the Spring container
32  * for unit tests: simply populate your POJOs in plain JUnit tests!
33  *
34  * <p>This supports two modes of populating the test:
35  * <ul>
36  * <li>Via Setter Dependency Injection. Simply express dependencies on objects
37  * in the test fixture, and they will be satisfied by autowiring by type.
38  * <li>Via Field Injection. Declare protected variables of the required type
39  * which match named beans in the context. This is autowire by name,
40  * rather than type. This approach is based on an approach originated by
41  * Ara Abrahmian. Setter Dependency Injection is the default: set the
42  * "populateProtectedVariables" property to true in the constructor to switch
43  * on Field Injection.
44  * </ul>
45  *
46  * @author Rod Johnson
47  * @author Rob Harrop
48  * @author Rick Evans
49  * @since 1.1.1
50  * @see #setDirty
51  * @see #contextKey
52  * @see #getContext
53  * @see #getConfigLocations
54  */

55 public abstract class AbstractDependencyInjectionSpringContextTests extends AbstractSingleSpringContextTests {
56
57     /**
58      * Constant that indicates no autowiring at all.
59      * @see #setAutowireMode
60      */

61     public static final int AUTOWIRE_NO = 0;
62
63     /**
64      * Constant that indicates autowiring bean properties by name.
65      * @see #setAutowireMode
66      */

67     public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
68
69     /**
70      * Constant that indicates autowiring bean properties by type.
71      * @see #setAutowireMode
72      */

73     public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
74
75
76     private boolean populateProtectedVariables = false;
77
78     private int autowireMode = AUTOWIRE_BY_TYPE;
79
80     private boolean dependencyCheck = true;
81
82     private String JavaDoc[] managedVariableNames;
83
84
85     /**
86      * Default constructor for AbstractDependencyInjectionSpringContextTests.
87      */

88     public AbstractDependencyInjectionSpringContextTests() {
89     }
90
91     /**
92      * Constructor for AbstractDependencyInjectionSpringContextTests with a JUnit name.
93      * @param name the name of this text fixture
94      */

95     public AbstractDependencyInjectionSpringContextTests(String JavaDoc name) {
96         super(name);
97     }
98
99
100     /**
101      * Set whether to populate protected variables of this test case.
102      * Default is "false".
103      */

104     public final void setPopulateProtectedVariables(boolean populateFields) {
105         this.populateProtectedVariables = populateFields;
106     }
107
108     /**
109      * Return whether to populate protected variables of this test case.
110      */

111     public final boolean isPopulateProtectedVariables() {
112         return this.populateProtectedVariables;
113     }
114
115     /**
116      * Set the autowire mode for test properties set by Dependency Injection.
117      * <p>The default is "AUTOWIRE_BY_TYPE". Can be set to "AUTOWIRE_BY_NAME"
118      * or "AUTOWIRE_NO" instead.
119      * @see #AUTOWIRE_BY_TYPE
120      * @see #AUTOWIRE_BY_NAME
121      * @see #AUTOWIRE_NO
122      */

123     public final void setAutowireMode(int autowireMode) {
124         this.autowireMode = autowireMode;
125     }
126
127     /**
128      * Return the autowire mode for test properties set by Dependency Injection.
129      */

130     public final int getAutowireMode() {
131         return this.autowireMode;
132     }
133
134     /**
135      * Set whether or not dependency checking should be performed
136      * for test properties set by Dependency Injection.
137      * <p>The default is "true", meaning that tests cannot be run
138      * unless all properties are populated.
139      */

140     public final void setDependencyCheck(boolean dependencyCheck) {
141         this.dependencyCheck = dependencyCheck;
142     }
143
144     /**
145      * Return whether or not dependency checking should be performed
146      * for test properties set by Dependency Injection.
147      */

148     public final boolean isDependencyCheck() {
149         return this.dependencyCheck;
150     }
151
152
153     /**
154      * Prepare this test instance, injecting dependencies into its
155      * protected fields and its bean properties.
156      */

157     protected void prepareTestInstance() throws Exception JavaDoc {
158         injectDependencies();
159     }
160
161     /**
162      * Inject dependencies into 'this' instance (that is, this test instance).
163      * <p>The default implementation populates protected variables if the
164      * {@link #populateProtectedVariables() appropriate flag is set}, else
165      * uses autowiring if autowiring is switched on (which it is by default).
166      * <p>Override this method if you need full control over how
167      * dependencies are injected into the test instance.
168      * @throws Exception in case of dependency injection failure
169      * @see #populateProtectedVariables()
170      */

171     protected void injectDependencies() throws Exception JavaDoc {
172         if (isPopulateProtectedVariables()) {
173             if (this.managedVariableNames == null) {
174                 initManagedVariableNames();
175             }
176             populateProtectedVariables();
177         }
178         else if (getAutowireMode() != AUTOWIRE_NO) {
179             getApplicationContext().getBeanFactory().autowireBeanProperties(
180                     this, getAutowireMode(), isDependencyCheck());
181         }
182     }
183
184     private void initManagedVariableNames() throws IllegalAccessException JavaDoc {
185         LinkedList JavaDoc managedVarNames = new LinkedList JavaDoc();
186         Class JavaDoc clazz = getClass();
187
188         do {
189             Field JavaDoc[] fields = clazz.getDeclaredFields();
190             if (logger.isDebugEnabled()) {
191                 logger.debug("Found " + fields.length + " fields on " + clazz);
192             }
193
194             for (int i = 0; i < fields.length; i++) {
195                 Field JavaDoc field = fields[i];
196                 field.setAccessible(true);
197                 if (logger.isDebugEnabled()) {
198                     logger.debug("Candidate field: " + field);
199                 }
200                 if (isProtectedInstanceField(field)) {
201                     Object JavaDoc oldValue = field.get(this);
202                     if (oldValue == null) {
203                         managedVarNames.add(field.getName());
204                         if (logger.isDebugEnabled()) {
205                             logger.debug("Added managed variable '" + field.getName() + "'");
206                         }
207                     }
208                     else {
209                         if (logger.isDebugEnabled()) {
210                             logger.debug("Rejected managed variable '" + field.getName() + "'");
211                         }
212                     }
213                 }
214             }
215             clazz = clazz.getSuperclass();
216         }
217         while (!clazz.equals(AbstractDependencyInjectionSpringContextTests.class));
218
219         this.managedVariableNames = (String JavaDoc[]) managedVarNames.toArray(new String JavaDoc[managedVarNames.size()]);
220     }
221
222     private boolean isProtectedInstanceField(Field JavaDoc field) {
223         int modifiers = field.getModifiers();
224         return !Modifier.isStatic(modifiers) && Modifier.isProtected(modifiers);
225     }
226
227     private void populateProtectedVariables() throws IllegalAccessException JavaDoc {
228         for (int i = 0; i < this.managedVariableNames.length; i++) {
229             String JavaDoc varName = this.managedVariableNames[i];
230             Object JavaDoc bean = null;
231             try {
232                 Field JavaDoc field = findField(getClass(), varName);
233                 bean = getApplicationContext().getBean(varName, field.getType());
234                 field.setAccessible(true);
235                 field.set(this, bean);
236                 if (logger.isDebugEnabled()) {
237                     logger.debug("Populated field: " + field);
238                 }
239             }
240             catch (NoSuchFieldException JavaDoc ex) {
241                 if (logger.isWarnEnabled()) {
242                     logger.warn("No field with name '" + varName + "'");
243                 }
244             }
245             catch (NoSuchBeanDefinitionException ex) {
246                 if (logger.isWarnEnabled()) {
247                     logger.warn("No bean with name '" + varName + "'");
248                 }
249             }
250         }
251     }
252
253     private Field JavaDoc findField(Class JavaDoc clazz, String JavaDoc name) throws NoSuchFieldException JavaDoc {
254         try {
255             return clazz.getDeclaredField(name);
256         }
257         catch (NoSuchFieldException JavaDoc ex) {
258             Class JavaDoc superclass = clazz.getSuperclass();
259             if (superclass != AbstractSpringContextTests.class) {
260                 return findField(superclass, name);
261             }
262             else {
263                 throw ex;
264             }
265         }
266     }
267
268 }
269
Popular Tags