KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > test > annotation > AbstractAnnotationAwareTransactionalTests


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.annotation;
18
19 import java.lang.reflect.Method JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import javax.sql.DataSource JavaDoc;
23
24 import org.apache.commons.logging.Log;
25
26 import org.springframework.context.ApplicationContext;
27 import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
28 import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
29 import org.springframework.transaction.TransactionDefinition;
30 import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
31 import org.springframework.transaction.interceptor.TransactionAttributeSource;
32
33 /**
34  * Java 5 specific subclass of
35  * {@link AbstractTransactionalDataSourceSpringContextTests}, exposing a
36  * {@link SimpleJdbcTemplate} and obeying annotations for transaction control.
37  *
38  * <p>For example, test methods can be annotated with the regular Spring
39  * {@link org.springframework.transaction.annotation.Transactional} annotation
40  * (for example, to force execution in a read-only transaction) or with the
41  * {@link NotTransactional} annotation to prevent any transaction being created
42  * at all.
43  *
44  * @author Rod Johnson
45  * @since 2.0
46  */

47 public abstract class AbstractAnnotationAwareTransactionalTests
48         extends AbstractTransactionalDataSourceSpringContextTests {
49     
50     protected SimpleJdbcTemplate simpleJdbcTemplate;
51     
52     private TransactionAttributeSource transactionAttributeSource = new AnnotationTransactionAttributeSource();
53     
54     protected ProfileValueSource profileValueSource = SystemProfileValueSource.getInstance();
55
56
57     @Override JavaDoc
58     public void setDataSource(DataSource JavaDoc dataSource) {
59         super.setDataSource(dataSource);
60         // JdbcTemplate will be identically configured
61
this.simpleJdbcTemplate = new SimpleJdbcTemplate(this.jdbcTemplate);
62     }
63
64     // TODO code to try to load (and cache!) ProfileValueSource
65
// from a given URL? It's easy enough to do, of course.
66
protected void findUniqueProfileValueSourceFromContext(ApplicationContext ac) {
67         Map JavaDoc beans = ac.getBeansOfType(ProfileValueSource.class);
68         if (beans.size() == 1) {
69             this.profileValueSource = (ProfileValueSource) beans.values().iterator().next();
70         }
71     }
72
73
74     /**
75      * Overridden to populate transaction definition from annotations.
76      */

77     @Override JavaDoc
78     public void runBare() throws Throwable JavaDoc {
79         // getName will return the name of the method being run.
80
if (isDisabledInThisEnvironment(getName())) {
81             // Let superclass log that we didn't run the test.
82
super.runBare();
83             return;
84         }
85         
86         // Use same algorithm as JUnit itself to retrieve the test method
87
// about to be executed (the method name is returned by getName).
88
// It has to be public so we can retrieve it
89
final Method JavaDoc testMethod = getClass().getMethod(getName(), (Class JavaDoc[]) null);
90         
91         if (isDisabledInThisEnvironment(testMethod)) {
92             logger.info("**** " + getClass().getName() + "." + getName() + " disabled in this environment: " +
93                     "Total disabled tests=" + getDisabledTestCount());
94             recordDisabled();
95             return;
96         }
97         
98         TransactionDefinition explicitTransactionDefinition =
99                 this.transactionAttributeSource.getTransactionAttribute(testMethod, getClass());
100         if (explicitTransactionDefinition != null) {
101             logger.info("Custom transaction definition [" + explicitTransactionDefinition + " for test method " + getName());
102             setTransactionDefinition(explicitTransactionDefinition);
103         }
104         else if (testMethod.isAnnotationPresent(NotTransactional.class)) {
105             // Don't have any transaction...
106
preventTransaction();
107         }
108         
109         // Let JUnit handle execution. We're just changing the state of the
110
// test class first.
111
runTestTimed(
112                 new TestExecutionCallback() {
113                     public void run() throws Throwable JavaDoc {
114                         try {
115                             AbstractAnnotationAwareTransactionalTests.super.runBare();
116                         }
117                         finally {
118                             // Mark the context to be blown
119
// away if the test was annotated to result
120
// in setDirty being invoked automatically
121
if (testMethod.isAnnotationPresent(DirtiesContext.class)) {
122                                 AbstractAnnotationAwareTransactionalTests.this.setDirty();
123                             }
124                         }
125                     }
126                 },
127                 testMethod,
128                 logger);
129     }
130
131     protected boolean isDisabledInThisEnvironment(Method JavaDoc testMethod) {
132         IfProfileValue inProfile = testMethod.getAnnotation(IfProfileValue.class);
133         if (inProfile == null) {
134             inProfile = getClass().getAnnotation(IfProfileValue.class);
135         }
136
137         if (inProfile != null) {
138             // May be true
139
return !this.profileValueSource.get(inProfile.name()).equals(inProfile.value());
140         }
141         else {
142             return false;
143         }
144
145         // TODO IfNotProfileValue
146
}
147
148
149     private static void runTestTimed(TestExecutionCallback tec, Method JavaDoc testMethod, Log logger) throws Throwable JavaDoc {
150         Timed timed = testMethod.getAnnotation(Timed.class);
151         
152         if (timed == null) {
153             runTest(tec, testMethod, logger);
154         }
155         else {
156             long startTime = System.currentTimeMillis();
157             try {
158                 runTest(tec, testMethod, logger);
159             }
160             finally {
161                 long elapsed = System.currentTimeMillis() - startTime;
162                 if (elapsed > timed.millis()) {
163                     fail("Took " + elapsed + " ms; limit was " + timed.millis());
164                 }
165             }
166         }
167     }
168     
169     private static void runTest(TestExecutionCallback tec, Method JavaDoc testMethod, Log logger) throws Throwable JavaDoc {
170         ExpectedException ee = testMethod.getAnnotation(ExpectedException.class);
171         Repeat repeat = testMethod.getAnnotation(Repeat.class);
172         
173         int runs = (repeat != null) ? repeat.value() : 1;
174         
175         for (int i = 0; i < runs; i++) {
176             try {
177                 if (i > 0 && logger != null) {
178                     logger.info("Repetition " + i + " of test " + testMethod.getName());
179                 }
180                 tec.run();
181                 if (ee != null) {
182                     fail("Expected throwable of class " + ee.value());
183                 }
184             }
185             catch (Throwable JavaDoc t) {
186                 if (ee == null) {
187                     throw t;
188                 }
189                 if (ee.value().isAssignableFrom(t.getClass())) {
190                     // Ok
191
}
192                 else {
193                     //fail("Expected throwable of class " + ee.value() + "; got " + t);
194
// Throw the unexpected problem throwable
195
throw t;
196                 }
197             }
198         }
199     }
200
201
202     private static interface TestExecutionCallback {
203
204         void run() throws Throwable JavaDoc;
205     }
206
207 }
208
Popular Tags