All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests Maven / Gradle / Ivy

There is a newer version: 5.3.34
Show newest version
/*
 * Copyright 2002-2007 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.test.annotation;

import java.lang.reflect.Method;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;

import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttributeSource;

/**
 * Java 5 specific subclass of
 * {@link AbstractTransactionalDataSourceSpringContextTests}, exposing a
 * {@link SimpleJdbcTemplate} and obeying annotations for transaction control.
 *
 * 

For example, test methods can be annotated with the regular Spring * {@link org.springframework.transaction.annotation.Transactional} annotation * (for example, to force execution in a read-only transaction) or with the * {@link NotTransactional} annotation to prevent any transaction being created * at all. * * @author Rod Johnson * @since 2.0 */ public abstract class AbstractAnnotationAwareTransactionalTests extends AbstractTransactionalDataSourceSpringContextTests { protected SimpleJdbcTemplate simpleJdbcTemplate; private TransactionAttributeSource transactionAttributeSource = new AnnotationTransactionAttributeSource(); protected ProfileValueSource profileValueSource = SystemProfileValueSource.getInstance(); @Override public void setDataSource(DataSource dataSource) { super.setDataSource(dataSource); // JdbcTemplate will be identically configured this.simpleJdbcTemplate = new SimpleJdbcTemplate(this.jdbcTemplate); } // TODO code to try to load (and cache!) ProfileValueSource // from a given URL? It's easy enough to do, of course. protected void findUniqueProfileValueSourceFromContext(ApplicationContext ac) { Map beans = ac.getBeansOfType(ProfileValueSource.class); if (beans.size() == 1) { this.profileValueSource = (ProfileValueSource) beans.values().iterator().next(); } } /** * Overridden to populate transaction definition from annotations. */ @Override public void runBare() throws Throwable { // getName will return the name of the method being run. if (isDisabledInThisEnvironment(getName())) { // Let superclass log that we didn't run the test. super.runBare(); return; } // Use same algorithm as JUnit itself to retrieve the test method // about to be executed (the method name is returned by getName). // It has to be public so we can retrieve it final Method testMethod = getClass().getMethod(getName(), (Class[]) null); if (isDisabledInThisEnvironment(testMethod)) { logger.info("**** " + getClass().getName() + "." + getName() + " disabled in this environment: " + "Total disabled tests=" + getDisabledTestCount()); recordDisabled(); return; } TransactionDefinition explicitTransactionDefinition = this.transactionAttributeSource.getTransactionAttribute(testMethod, getClass()); if (explicitTransactionDefinition != null) { logger.info("Custom transaction definition [" + explicitTransactionDefinition + " for test method " + getName()); setTransactionDefinition(explicitTransactionDefinition); } else if (testMethod.isAnnotationPresent(NotTransactional.class)) { // Don't have any transaction... preventTransaction(); } // Let JUnit handle execution. We're just changing the state of the // test class first. runTestTimed( new TestExecutionCallback() { public void run() throws Throwable { try { AbstractAnnotationAwareTransactionalTests.super.runBare(); } finally { // Mark the context to be blown // away if the test was annotated to result // in setDirty being invoked automatically if (testMethod.isAnnotationPresent(DirtiesContext.class)) { AbstractAnnotationAwareTransactionalTests.this.setDirty(); } } } }, testMethod, logger); } protected boolean isDisabledInThisEnvironment(Method testMethod) { IfProfileValue inProfile = testMethod.getAnnotation(IfProfileValue.class); if (inProfile == null) { inProfile = getClass().getAnnotation(IfProfileValue.class); } if (inProfile != null) { // May be true return !this.profileValueSource.get(inProfile.name()).equals(inProfile.value()); } else { return false; } // TODO IfNotProfileValue } private static void runTestTimed(TestExecutionCallback tec, Method testMethod, Log logger) throws Throwable { Timed timed = testMethod.getAnnotation(Timed.class); if (timed == null) { runTest(tec, testMethod, logger); } else { long startTime = System.currentTimeMillis(); try { runTest(tec, testMethod, logger); } finally { long elapsed = System.currentTimeMillis() - startTime; if (elapsed > timed.millis()) { fail("Took " + elapsed + " ms; limit was " + timed.millis()); } } } } private static void runTest(TestExecutionCallback tec, Method testMethod, Log logger) throws Throwable { ExpectedException ee = testMethod.getAnnotation(ExpectedException.class); Repeat repeat = testMethod.getAnnotation(Repeat.class); int runs = (repeat != null) ? repeat.value() : 1; for (int i = 0; i < runs; i++) { try { if (i > 0 && logger != null) { logger.info("Repetition " + i + " of test " + testMethod.getName()); } tec.run(); if (ee != null) { fail("Expected throwable of class " + ee.value()); } } catch (Throwable t) { if (ee == null) { throw t; } if (ee.value().isAssignableFrom(t.getClass())) { // Ok } else { //fail("Expected throwable of class " + ee.value() + "; got " + t); // Throw the unexpected problem throwable throw t; } } } } private static interface TestExecutionCallback { void run() throws Throwable; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy