diff --git a/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java b/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java index 809f03fce63..8895a0341ad 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -24,25 +24,36 @@ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; /** - * Test annotation used to indicate whether or not the transaction for the - * annotated test method should be rolled back after the test method - * has completed. If {@code true}, the transaction will be rolled back; - * otherwise, the transaction will be committed. + * Test annotation used to indicate whether a test-managed transaction + * should be rolled back after the test method has completed. + * + *

Consult the class-level Javadoc for + * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener} + * for an explanation of test-managed transactions. + * + *

When declared as a class-level annotation, {@code @Rollback} defines + * the default rollback semantics for all test methods within the test class + * hierarchy. When declared as a method-level annotation, {@code @Rollback} + * defines rollback semantics for the specific test method, potentially + * overriding class-level default rollback semantics. * *

As of Spring Framework 4.0, this annotation may be used as a * meta-annotation to create custom composed annotations. * * @author Sam Brannen * @since 2.5 + * @see org.springframework.test.context.transaction.TransactionalTestExecutionListener */ @Documented @Retention(RUNTIME) -@Target({ METHOD, ANNOTATION_TYPE }) +@Target({ TYPE, METHOD, ANNOTATION_TYPE }) public @interface Rollback { /** - * Whether or not the transaction for the annotated method should be rolled - * back after the method has completed. + * Whether the test-managed transaction should be rolled back + * after the test method has completed. + *

If {@code true}, the transaction will be rolled back; otherwise, + * the transaction will be committed. */ boolean value() default true; diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java index 39167db179f..3b65d69056f 100644 --- a/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TestContextTransactionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -36,8 +36,8 @@ import org.springframework.util.StringUtils; /** * Utility methods for working with transactions and data access related beans - * within the Spring TestContext Framework. Mainly for internal use - * within the framework. + * within the Spring TestContext Framework. + *

Mainly for internal use within the framework. * * @author Sam Brannen * @author Juergen Hoeller @@ -146,6 +146,8 @@ public abstract class TestContextTransactionUtils { * @return the transaction manager to use, or {@code null} if not found * @throws BeansException if an error occurs while retrieving an explicitly * named transaction manager + * @throws IllegalStateException if more than one TransactionManagementConfigurer + * exists in the ApplicationContext */ public static PlatformTransactionManager retrieveTransactionManager(TestContext testContext, String name) { Assert.notNull(testContext, "TestContext must not be null"); diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfiguration.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfiguration.java index 4d73bc636ec..44ef346bf29 100644 --- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfiguration.java +++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfiguration.java @@ -39,7 +39,10 @@ import java.lang.annotation.Target; * @see org.springframework.test.context.jdbc.SqlConfig * @see org.springframework.test.context.jdbc.SqlConfig#transactionManager * @see org.springframework.test.context.ContextConfiguration + * @deprecated As of Spring Framework 4.2, use {@code @Rollback} at the class + * level and the {@code transactionManager} qualifier in {@code @Transactional}. */ +@Deprecated @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @@ -48,7 +51,7 @@ public @interface TransactionConfiguration { /** * The bean name of the {@link org.springframework.transaction.PlatformTransactionManager - * PlatformTransactionManager} that should be used to drive transactions. + * PlatformTransactionManager} that should be used to drive test-managed transactions. * *

The name is only used if there is more than one bean of type * {@code PlatformTransactionManager} in the test's {@code ApplicationContext}. @@ -76,7 +79,7 @@ public @interface TransactionConfiguration { String transactionManager() default ""; /** - * Should transactions be rolled back by default? + * Whether test-managed transactions should be rolled back by default. */ boolean defaultRollback() default true; diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfigurationAttributes.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfigurationAttributes.java index c6124703b87..60dd05cad54 100644 --- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfigurationAttributes.java +++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionConfigurationAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2015 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. @@ -36,14 +36,27 @@ public class TransactionConfigurationAttributes { /** - * Construct a new TransactionConfigurationAttributes instance from the - * supplied arguments. + * Construct a new {@code TransactionConfigurationAttributes} instance + * using an empty string for the bean name of the + * {@link PlatformTransactionManager} and {@code true} for the default + * rollback flag. + * @see #TransactionConfigurationAttributes(String, boolean) + */ + public TransactionConfigurationAttributes() { + this("", true); + } + + /** + * Construct a new {@code TransactionConfigurationAttributes} instance + * from the supplied arguments. * @param transactionManagerName the bean name of the - * {@link PlatformTransactionManager} that is to be used to drive transactions - * @param defaultRollback whether or not transactions should be rolled back by default + * {@link PlatformTransactionManager} that is to be used to drive + * test-managed transactions + * @param defaultRollback whether or not test-managed transactions + * should be rolled back by default */ public TransactionConfigurationAttributes(String transactionManagerName, boolean defaultRollback) { - Assert.notNull(transactionManagerName, "transactionManagerName can not be null"); + Assert.notNull(transactionManagerName, "transactionManagerName must not be null"); this.transactionManagerName = transactionManagerName; this.defaultRollback = defaultRollback; } @@ -51,14 +64,14 @@ public class TransactionConfigurationAttributes { /** * Get the bean name of the {@link PlatformTransactionManager} that is to - * be used to drive transactions. + * be used to drive test-managed transactions. */ public final String getTransactionManagerName() { return this.transactionManagerName; } /** - * Whether or not transactions should be rolled back by default. + * Whether test-managed transactions should be rolled back by default. * @return the default rollback flag */ public final boolean isDefaultRollback() { diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java index e108393363a..659a9694f65 100644 --- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java @@ -30,7 +30,6 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.core.annotation.AnnotationUtils; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.TestContext; import org.springframework.test.context.support.AbstractTestExecutionListener; @@ -84,9 +83,8 @@ import static org.springframework.core.annotation.AnnotationUtils.*; *

Declarative Rollback and Commit Behavior

*

By default, test transactions will be automatically rolled back * after completion of the test; however, transactional commit and rollback - * behavior can be configured declaratively via the class-level - * {@link TransactionConfiguration @TransactionConfiguration} and method-level - * {@link Rollback @Rollback} annotations. + * behavior can be configured declaratively via the {@link Rollback @Rollback} + * annotation at the class level and at the method level. * *

Programmatic Transaction Management

*

As of Spring Framework 4.1, it is possible to interact with test-managed @@ -107,13 +105,11 @@ import static org.springframework.core.annotation.AnnotationUtils.*; * {@link PlatformTransactionManager} bean to be defined in the Spring * {@code ApplicationContext} for the test. In case there are multiple * instances of {@code PlatformTransactionManager} within the test's - * {@code ApplicationContext}, {@code @TransactionConfiguration} supports - * configuring the bean name of the {@code PlatformTransactionManager} that - * should be used to drive transactions. Alternatively, a qualifier - * may be declared via - * {@link org.springframework.transaction.annotation.Transactional#value @Transactional("myQualifier")}, or - * {@link org.springframework.transaction.annotation.TransactionManagementConfigurer TransactionManagementConfigurer} - * can be implemented by an + * {@code ApplicationContext}, a qualifier may be declared via + * {@link org.springframework.transaction.annotation.Transactional @Transactional} + * (e.g., {@code @Transactional("myTxMgr")} or {@code @Transactional(transactionManger = "myTxMgr")}, + * or {@link org.springframework.transaction.annotation.TransactionManagementConfigurer + * TransactionManagementConfigurer} can be implemented by an * {@link org.springframework.context.annotation.Configuration @Configuration} * class. See {@link TestContextTransactionUtils#retrieveTransactionManager} * for details on the algorithm used to look up a transaction manager in @@ -122,7 +118,6 @@ import static org.springframework.core.annotation.AnnotationUtils.*; * @author Sam Brannen * @author Juergen Hoeller * @since 2.5 - * @see TransactionConfiguration * @see org.springframework.transaction.annotation.TransactionManagementConfigurer * @see org.springframework.transaction.annotation.Transactional * @see org.springframework.test.annotation.Rollback @@ -134,8 +129,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis private static final Log logger = LogFactory.getLog(TransactionalTestExecutionListener.class); - private static final TransactionConfiguration defaultTransactionConfiguration = - AnnotationUtils.synthesizeAnnotation(TransactionConfiguration.class); + private static final TransactionConfigurationAttributes defaultTxConfigAttributes = new TransactionConfigurationAttributes(); protected final TransactionAttributeSource attributeSource = new AnnotationTransactionAttributeSource(); @@ -229,8 +223,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis /** * Run all {@link BeforeTransaction @BeforeTransaction} methods for the - * specified {@link TestContext test context}. If one of the methods fails, - * however, the caught exception will be rethrown in a wrapped + * specified {@linkplain TestContext test context}. If one of the methods + * fails, however, the caught exception will be rethrown in a wrapped * {@link RuntimeException}, and the remaining methods will not * be given a chance to execute. * @param testContext the current test context @@ -255,8 +249,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis /** * Run all {@link AfterTransaction @AfterTransaction} methods for the - * specified {@link TestContext test context}. If one of the methods fails, - * the caught exception will be logged as an error, and the remaining + * specified {@linkplain TestContext test context}. If one of the methods + * fails, the caught exception will be logged as an error, and the remaining * methods will be given a chance to execute. After all methods have * executed, the first caught exception, if any, will be rethrown. * @param testContext the current test context @@ -295,7 +289,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis } /** - * Get the {@link PlatformTransactionManager transaction manager} to use + * Get the {@linkplain PlatformTransactionManager transaction manager} to use * for the supplied {@linkplain TestContext test context} and {@code qualifier}. *

Delegates to {@link #getTransactionManager(TestContext)} if the * supplied {@code qualifier} is {@code null} or empty. @@ -334,8 +328,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis } /** - * Get the {@link PlatformTransactionManager transaction manager} to use - * for the supplied {@link TestContext test context}. + * Get the {@linkplain PlatformTransactionManager transaction manager} + * to use for the supplied {@linkplain TestContext test context}. *

The default implementation simply delegates to * {@link TestContextTransactionUtils#retrieveTransactionManager}. * @param testContext the test context for which the transaction manager @@ -343,6 +337,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis * @return the transaction manager to use, or {@code null} if not found * @throws BeansException if an error occurs while retrieving an explicitly * named transaction manager + * @throws IllegalStateException if more than one TransactionManagementConfigurer + * exists in the ApplicationContext * @see #getTransactionManager(TestContext, String) */ protected PlatformTransactionManager getTransactionManager(TestContext testContext) { @@ -352,21 +348,45 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis /** * Determine whether or not to rollback transactions by default for the - * supplied {@link TestContext test context}. + * supplied {@linkplain TestContext test context}. + *

Supports {@link Rollback @Rollback} or + * {@link TransactionConfiguration @TransactionConfiguration} at the + * class-level. * @param testContext the test context for which the default rollback flag * should be retrieved * @return the default rollback flag for the supplied test context * @throws Exception if an error occurs while determining the default rollback flag */ protected final boolean isDefaultRollback(TestContext testContext) throws Exception { - return retrieveConfigurationAttributes(testContext).isDefaultRollback(); + Class testClass = testContext.getTestClass(); + Rollback rollback = findAnnotation(testClass, Rollback.class); + boolean rollbackPresent = (rollback != null); + TransactionConfigurationAttributes txConfigAttributes = retrieveConfigurationAttributes(testContext); + + if (rollbackPresent && txConfigAttributes != defaultTxConfigAttributes) { + throw new IllegalStateException(String.format("Test class [%s] is annotated with both @Rollback " + + "and @TransactionConfiguration, but only one is permitted.", testClass.getName())); + } + + if (rollbackPresent) { + boolean defaultRollback = rollback.value(); + if (logger.isDebugEnabled()) { + logger.debug(String.format("Retrieved default @Rollback(%s) for test class [%s].", defaultRollback, + testClass.getName())); + } + return defaultRollback; + } + + // else + return txConfigAttributes.isDefaultRollback(); } /** * Determine whether or not to rollback transactions for the supplied - * {@link TestContext test context} by taking into consideration the - * {@link #isDefaultRollback(TestContext) default rollback} flag and a - * possible method-level override via the {@link Rollback} annotation. + * {@linkplain TestContext test context} by taking into consideration the + * {@linkplain #isDefaultRollback(TestContext) default rollback} flag and a + * possible method-level override via the {@link Rollback @Rollback} + * annotation. * @param testContext the test context for which the rollback flag * should be retrieved * @return the rollback flag for the supplied test context @@ -458,8 +478,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis } /** - * Determine if the supplied {@link Method current method} is shadowed - * by a {@link Method previous method}. + * Determine if the supplied {@linkplain Method current method} is + * shadowed by a {@linkplain Method previous method}. *

Note: This code has been borrowed from * {@link org.junit.internal.runners.TestClass#isShadowed(Method, Method)}. * @param current the current method @@ -482,17 +502,20 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis } /** - * Retrieves the {@link TransactionConfigurationAttributes} for the - * specified {@link Class class} which may optionally declare or inherit - * {@link TransactionConfiguration @TransactionConfiguration}. If - * {@code @TransactionConfiguration} is not present for the supplied - * class, the default values for attributes defined in - * {@code @TransactionConfiguration} will be used instead. + * Retrieve the {@link TransactionConfigurationAttributes} for the + * supplied {@link TestContext} whose {@linkplain Class test class} + * may optionally declare or inherit + * {@link TransactionConfiguration @TransactionConfiguration}. + *

If {@code @TransactionConfiguration} is not present for the + * supplied {@code TestContext}, a default instance of + * {@code TransactionConfigurationAttributes} will be used instead. * @param testContext the test context for which the configuration * attributes should be retrieved * @return the TransactionConfigurationAttributes instance for this listener, * potentially cached + * @see TransactionConfigurationAttributes#TransactionConfigurationAttributes() */ + @SuppressWarnings("deprecation") TransactionConfigurationAttributes retrieveConfigurationAttributes(TestContext testContext) { if (this.configurationAttributes == null) { Class clazz = testContext.getTestClass(); @@ -501,18 +524,15 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis TransactionConfiguration.class); if (logger.isDebugEnabled()) { logger.debug(String.format("Retrieved @TransactionConfiguration [%s] for test class [%s].", - txConfig, clazz)); + txConfig, clazz.getName())); } - if (txConfig == null) { - txConfig = defaultTransactionConfiguration; - } + TransactionConfigurationAttributes configAttributes = (txConfig == null ? defaultTxConfigAttributes + : new TransactionConfigurationAttributes(txConfig.transactionManager(), txConfig.defaultRollback())); - TransactionConfigurationAttributes configAttributes = new TransactionConfigurationAttributes( - txConfig.transactionManager(), txConfig.defaultRollback()); if (logger.isDebugEnabled()) { - logger.debug(String.format("Using TransactionConfigurationAttributes %s for class [%s].", - configAttributes, clazz)); + logger.debug(String.format("Using TransactionConfigurationAttributes %s for test class [%s].", + configAttributes, clazz.getName())); } this.configurationAttributes = configAttributes; } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java new file mode 100644 index 00000000000..04b639cc52d --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseRollbackAnnotationTransactionalTests.java @@ -0,0 +1,110 @@ +/* + * Copyright 2002-2015 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.context.junit4; + +import javax.sql.DataSource; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.Assert.*; +import static org.springframework.test.transaction.TransactionTestUtils.*; + +/** + * Integration test which verifies proper transactional behavior when the + * default rollback flag is set to {@code false} via {@link Rollback @Rollback}. + * + *

Also tests configuration of the transaction manager qualifier configured + * via {@link Transactional @Transactional}. + * + * @author Sam Brannen + * @since 4.2 + * @see Rollback + * @see Transactional#transactionManager + * @see DefaultRollbackFalseTransactionalTests + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(inheritLocations = false) +@Transactional("txMgr") +@Rollback(false) +public class DefaultRollbackFalseRollbackAnnotationTransactionalTests extends AbstractTransactionalSpringRunnerTests { + + private static JdbcTemplate jdbcTemplate; + + + @Autowired + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Before + public void verifyInitialTestData() { + clearPersonTable(jdbcTemplate); + assertEquals("Adding bob", 1, addPerson(jdbcTemplate, BOB)); + assertEquals("Verifying the initial number of rows in the person table.", 1, + countRowsInPersonTable(jdbcTemplate)); + } + + @Test + public void modifyTestDataWithinTransaction() { + assertInTransaction(true); + assertEquals("Deleting bob", 1, deletePerson(jdbcTemplate, BOB)); + assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); + assertEquals("Adding sue", 1, addPerson(jdbcTemplate, SUE)); + assertEquals("Verifying the number of rows in the person table within a transaction.", 2, + countRowsInPersonTable(jdbcTemplate)); + } + + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", 2, + countRowsInPersonTable(jdbcTemplate)); + } + + + @Configuration + static class Config { + + @Bean + public PlatformTransactionManager txMgr() { + return new DataSourceTransactionManager(dataSource()); + } + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder()// + .generateUniqueName(true)// + .addScript("classpath:/org/springframework/test/context/junit4/person-schema.sql") // + .build(); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests.java similarity index 89% rename from spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests.java rename to spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests.java index cdd293203c7..df1c17cc943 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -23,7 +23,6 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.transaction.TransactionConfiguration; @@ -33,33 +32,27 @@ import static org.junit.Assert.*; import static org.springframework.test.transaction.TransactionTestUtils.*; /** - *

* JUnit 4 based integration test which verifies proper transactional behavior when the * {@link TransactionConfiguration#defaultRollback() defaultRollback} attribute * of the {@link TransactionConfiguration} annotation is set to {@code false}. - * Also tests configuration of the + *

Also tests configuration of the * {@link TransactionConfiguration#transactionManager() transaction manager name}. - *

* * @author Sam Brannen * @since 2.5 * @see TransactionConfiguration + * @see DefaultRollbackFalseRollbackAnnotationTransactionalTests */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @TransactionConfiguration(transactionManager = "txMgr", defaultRollback = false) @Transactional -public class DefaultRollbackFalseTransactionalSpringRunnerTests extends AbstractTransactionalSpringRunnerTests { +@SuppressWarnings("deprecation") +public class DefaultRollbackFalseTransactionalTests extends AbstractTransactionalSpringRunnerTests { - protected static JdbcTemplate jdbcTemplate; + private static JdbcTemplate jdbcTemplate; - @AfterClass - public static void verifyFinalTestData() { - assertEquals("Verifying the final number of rows in the person table after all tests.", 2, - countRowsInPersonTable(jdbcTemplate)); - } - @Before public void verifyInitialTestData() { clearPersonTable(jdbcTemplate); @@ -78,6 +71,12 @@ public class DefaultRollbackFalseTransactionalSpringRunnerTests extends Abstract countRowsInPersonTable(jdbcTemplate)); } + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", 2, + countRowsInPersonTable(jdbcTemplate)); + } + public static class DatabaseSetup { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java new file mode 100644 index 00000000000..16cee7b6f4e --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueRollbackAnnotationTransactionalTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2002-2015 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.context.junit4; + +import javax.sql.DataSource; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.Assert.*; +import static org.springframework.test.transaction.TransactionTestUtils.*; + +/** + * Integration test which verifies proper transactional behavior when the default + * rollback flag is explicitly set to {@code true} via {@link Rollback @Rollback}. + * + *

Also tests configuration of the transaction manager qualifier configured + * via {@link Transactional @Transactional}. + * + * @author Sam Brannen + * @since 4.2 + * @see Rollback + * @see Transactional#transactionManager + * @see DefaultRollbackTrueTransactionalTests + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(inheritLocations = false) +@Transactional("txMgr") +@Rollback(true) +public class DefaultRollbackTrueRollbackAnnotationTransactionalTests extends AbstractTransactionalSpringRunnerTests { + + private static int originalNumRows; + + private static JdbcTemplate jdbcTemplate; + + + @Autowired + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Before + public void verifyInitialTestData() { + originalNumRows = clearPersonTable(jdbcTemplate); + assertEquals("Adding bob", 1, addPerson(jdbcTemplate, BOB)); + assertEquals("Verifying the initial number of rows in the person table.", 1, + countRowsInPersonTable(jdbcTemplate)); + } + + @Test(timeout = 1000) + public void modifyTestDataWithinTransaction() { + assertInTransaction(true); + assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); + assertEquals("Adding sue", 1, addPerson(jdbcTemplate, SUE)); + assertEquals("Verifying the number of rows in the person table within a transaction.", 3, + countRowsInPersonTable(jdbcTemplate)); + } + + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, + countRowsInPersonTable(jdbcTemplate)); + } + + + @Configuration + static class Config { + + @Bean + public PlatformTransactionManager txMgr() { + return new DataSourceTransactionManager(dataSource()); + } + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder()// + .generateUniqueName(true)// + .addScript("classpath:/org/springframework/test/context/junit4/person-schema.sql") // + .build(); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests.java similarity index 92% rename from spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests.java rename to spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests.java index f55c2c6a956..873a6f64b8c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests.java @@ -23,7 +23,6 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.transaction.TransactionConfiguration; @@ -43,20 +42,16 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration +@Transactional @TransactionConfiguration(defaultRollback = true) -public class DefaultRollbackTrueTransactionalSpringRunnerTests extends AbstractTransactionalSpringRunnerTests { +@SuppressWarnings("deprecation") +public class DefaultRollbackTrueTransactionalTests extends AbstractTransactionalSpringRunnerTests { - protected static int originalNumRows; + private static int originalNumRows; - protected static JdbcTemplate jdbcTemplate; + private static JdbcTemplate jdbcTemplate; - @AfterClass - public static void verifyFinalTestData() { - assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, - countRowsInPersonTable(jdbcTemplate)); - } - @Before public void verifyInitialTestData() { originalNumRows = clearPersonTable(jdbcTemplate); @@ -66,7 +61,6 @@ public class DefaultRollbackTrueTransactionalSpringRunnerTests extends AbstractT } @Test(timeout = 1000) - @Transactional public void modifyTestDataWithinTransaction() { assertInTransaction(true); assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); @@ -75,6 +69,12 @@ public class DefaultRollbackTrueTransactionalSpringRunnerTests extends AbstractT countRowsInPersonTable(jdbcTemplate)); } + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, + countRowsInPersonTable(jdbcTemplate)); + } + public static class DatabaseSetup { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseRollbackAnnotationTransactionalTests.java new file mode 100644 index 00000000000..f94a3b25424 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseRollbackAnnotationTransactionalTests.java @@ -0,0 +1,82 @@ +/* + * Copyright 2002-2015 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.context.junit4; + +import javax.sql.DataSource; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; + +import static org.junit.Assert.*; +import static org.springframework.test.transaction.TransactionTestUtils.*; + +/** + * Extension of {@link DefaultRollbackFalseRollbackAnnotationTransactionalTests} + * which tests method-level rollback override behavior via the + * {@link Rollback @Rollback} annotation. + * + * @author Sam Brannen + * @since 4.2 + * @see Rollback + */ +public class RollbackOverrideDefaultRollbackFalseRollbackAnnotationTransactionalTests extends + DefaultRollbackFalseRollbackAnnotationTransactionalTests { + + private static int originalNumRows; + + private static JdbcTemplate jdbcTemplate; + + + @Autowired + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Before + @Override + public void verifyInitialTestData() { + originalNumRows = clearPersonTable(jdbcTemplate); + assertEquals("Adding bob", 1, addPerson(jdbcTemplate, BOB)); + assertEquals("Verifying the initial number of rows in the person table.", 1, + countRowsInPersonTable(jdbcTemplate)); + } + + @Test + @Rollback + @Override + public void modifyTestDataWithinTransaction() { + assertInTransaction(true); + assertEquals("Deleting bob", 1, deletePerson(jdbcTemplate, BOB)); + assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); + assertEquals("Adding sue", 1, addPerson(jdbcTemplate, SUE)); + assertEquals("Verifying the number of rows in the person table within a transaction.", 2, + countRowsInPersonTable(jdbcTemplate)); + } + + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, + countRowsInPersonTable(jdbcTemplate)); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests.java similarity index 86% rename from spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.java rename to spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests.java index 9acbbe143f2..1543008baac 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -31,7 +31,7 @@ import static org.junit.Assert.*; import static org.springframework.test.transaction.TransactionTestUtils.*; /** - * Extension of {@link DefaultRollbackFalseTransactionalSpringRunnerTests} which + * Extension of {@link DefaultRollbackFalseTransactionalTests} which * tests method-level rollback override behavior via the * {@link Rollback @Rollback} annotation. * @@ -40,20 +40,14 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @see Rollback */ @ContextConfiguration -public class RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests extends - DefaultRollbackFalseTransactionalSpringRunnerTests { +public class RollbackOverrideDefaultRollbackFalseTransactionalTests extends + DefaultRollbackFalseTransactionalTests { - protected static int originalNumRows; + private static int originalNumRows; - protected static JdbcTemplate jdbcTemplate; + private static JdbcTemplate jdbcTemplate; - @AfterClass - public static void verifyFinalTestData() { - assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, - countRowsInPersonTable(jdbcTemplate)); - } - @Before @Override public void verifyInitialTestData() { @@ -75,6 +69,12 @@ public class RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests countRowsInPersonTable(jdbcTemplate)); } + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", originalNumRows, + countRowsInPersonTable(jdbcTemplate)); + } + public static class DatabaseSetup { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueRollbackAnnotationTransactionalTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueRollbackAnnotationTransactionalTests.java new file mode 100644 index 00000000000..91b38858015 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueRollbackAnnotationTransactionalTests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2002-2015 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.context.junit4; + +import javax.sql.DataSource; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Rollback; + +import static org.junit.Assert.*; +import static org.springframework.test.transaction.TransactionTestUtils.*; + +/** + * Extension of {@link DefaultRollbackTrueRollbackAnnotationTransactionalTests} + * which tests method-level rollback override behavior via the + * {@link Rollback @Rollback} annotation. + * + * @author Sam Brannen + * @since 4.2 + * @see Rollback + */ +public class RollbackOverrideDefaultRollbackTrueRollbackAnnotationTransactionalTests extends + DefaultRollbackTrueRollbackAnnotationTransactionalTests { + + private static JdbcTemplate jdbcTemplate; + + + @Autowired + @Override + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + + @Before + @Override + public void verifyInitialTestData() { + clearPersonTable(jdbcTemplate); + assertEquals("Adding bob", 1, addPerson(jdbcTemplate, BOB)); + assertEquals("Verifying the initial number of rows in the person table.", 1, + countRowsInPersonTable(jdbcTemplate)); + } + + @Test + @Rollback(false) + @Override + public void modifyTestDataWithinTransaction() { + assertInTransaction(true); + assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); + assertEquals("Adding sue", 1, addPerson(jdbcTemplate, SUE)); + assertEquals("Verifying the number of rows in the person table within a transaction.", 3, + countRowsInPersonTable(jdbcTemplate)); + } + + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", 3, + countRowsInPersonTable(jdbcTemplate)); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests.java similarity index 85% rename from spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.java rename to spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests.java index 3a61a0ac637..f4edf977427 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -26,13 +26,12 @@ import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; -import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; import static org.springframework.test.transaction.TransactionTestUtils.*; /** - * Extension of {@link DefaultRollbackTrueTransactionalSpringRunnerTests} which + * Extension of {@link DefaultRollbackTrueTransactionalTests} which * tests method-level rollback override behavior via the * {@link Rollback @Rollback} annotation. * @@ -41,20 +40,14 @@ import static org.springframework.test.transaction.TransactionTestUtils.*; * @see Rollback */ @ContextConfiguration -public class RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests extends - DefaultRollbackTrueTransactionalSpringRunnerTests { +public class RollbackOverrideDefaultRollbackTrueTransactionalTests extends + DefaultRollbackTrueTransactionalTests { - protected static JdbcTemplate jdbcTemplate; + private static JdbcTemplate jdbcTemplate; - @AfterClass - public static void verifyFinalTestData() { - assertEquals("Verifying the final number of rows in the person table after all tests.", 3, - countRowsInPersonTable(jdbcTemplate)); - } - - @Override @Before + @Override public void verifyInitialTestData() { clearPersonTable(jdbcTemplate); assertEquals("Adding bob", 1, addPerson(jdbcTemplate, BOB)); @@ -62,10 +55,9 @@ public class RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests e countRowsInPersonTable(jdbcTemplate)); } - @Override @Test - @Transactional @Rollback(false) + @Override public void modifyTestDataWithinTransaction() { assertInTransaction(true); assertEquals("Adding jane", 1, addPerson(jdbcTemplate, JANE)); @@ -74,6 +66,12 @@ public class RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests e countRowsInPersonTable(jdbcTemplate)); } + @AfterClass + public static void verifyFinalTestData() { + assertEquals("Verifying the final number of rows in the person table after all tests.", 3, + countRowsInPersonTable(jdbcTemplate)); + } + public static class DatabaseSetup { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java index 6aff94bbad7..8f301117883 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4TestSuite.java @@ -55,7 +55,7 @@ import org.springframework.test.context.transaction.programmatic.ProgrammaticTxM * *

Note that tests included in this suite will be executed at least twice if * run from an automated build process, test runner, etc. that is not configured - * to exclude tests based on a "*TestSuite.class" pattern match. + * to exclude tests based on a {@code "*TestSuite.class"} pattern match. * * @author Sam Brannen * @since 2.5 @@ -104,10 +104,10 @@ StandardJUnit4FeaturesTests.class,// ConcreteTransactionalJUnit4SpringContextTests.class,// ClassLevelTransactionalSpringRunnerTests.class,// MethodLevelTransactionalSpringRunnerTests.class,// - DefaultRollbackTrueTransactionalSpringRunnerTests.class,// - DefaultRollbackFalseTransactionalSpringRunnerTests.class,// - RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.class,// - RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class,// + DefaultRollbackTrueTransactionalTests.class,// + DefaultRollbackFalseTransactionalTests.class,// + RollbackOverrideDefaultRollbackTrueTransactionalTests.class,// + RollbackOverrideDefaultRollbackFalseTransactionalTests.class,// BeforeAndAfterTransactionAnnotationTests.class,// TimedTransactionalSpringRunnerTests.class,// ProgrammaticTxMgmtTests.class,// diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java index 75ef234e174..321a985f623 100644 --- a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -20,9 +20,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; + import org.mockito.BDDMockito; +import org.springframework.core.annotation.AliasFor; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.TestContext; import org.springframework.transaction.PlatformTransactionManager; @@ -31,6 +35,8 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.SimpleTransactionStatus; +import static org.hamcrest.CoreMatchers.*; + import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; import static org.springframework.transaction.annotation.Propagation.*; @@ -41,6 +47,7 @@ import static org.springframework.transaction.annotation.Propagation.*; * @author Sam Brannen * @since 4.0 */ +@SuppressWarnings("deprecation") public class TransactionalTestExecutionListenerTests { private final PlatformTransactionManager tm = mock(PlatformTransactionManager.class); @@ -54,6 +61,9 @@ public class TransactionalTestExecutionListenerTests { private final TestContext testContext = mock(TestContext.class); + @Rule + public ExpectedException exception = ExpectedException.none(); + private void assertBeforeTestMethod(Class clazz) throws Exception { assertBeforeTestMethodWithTransactionalTestMethod(clazz); @@ -228,24 +238,86 @@ public class TransactionalTestExecutionListenerTests { "overriddenTxMgr", true); } + @Test + public void retrieveConfigurationAttributesWithEmptyTransactionalAnnotation() throws Exception { + assertTransactionConfigurationAttributes(EmptyTransactionalTestCase.class, "", true); + } + + @Test + public void retrieveConfigurationAttributesFromTransactionalAnnotationWithExplicitQualifier() throws Exception { + // The test class configures "tm" as the qualifier via @Transactional; + // however, retrieveConfigurationAttributes() only supports + // @TransactionConfiguration. So we actually expect "" as the qualifier here, + // relying on beforeTestMethod() to properly obtain the actual qualifier via the + // TransactionAttribute. + assertTransactionConfigurationAttributes(TransactionalWithExplicitQualifierTestCase.class, "", true); + } + + @Test + public void retrieveConfigurationAttributesFromTransactionalAnnotationViaMetaAnnotation() throws Exception { + // The test class configures "metaTxMgr" as the qualifier via @Transactional; + // however, retrieveConfigurationAttributes() only supports + // @TransactionConfiguration. So we actually expect "" as the qualifier here, + // relying on beforeTestMethod() to properly obtain the actual qualifier via the + // TransactionAttribute. + assertTransactionConfigurationAttributes(TransactionalViaMetaAnnotationTestCase.class, "", true); + } + + @Test + public void retrieveConfigurationAttributesFromTransactionalAnnotationViaMetaAnnotationWithExplicitQualifier() + throws Exception { + // The test class configures "overriddenTxMgr" as the qualifier via + // @Transactional; however, retrieveConfigurationAttributes() only supports + // @TransactionConfiguration. So we actually expect "" as the qualifier here, + // relying on beforeTestMethod() to properly obtain the actual qualifier via the + // TransactionAttribute. + assertTransactionConfigurationAttributes(TransactionalViaMetaAnnotationWithExplicitQualifierTestCase.class, "", + true); + } + @Test public void isRollbackWithMissingRollback() throws Exception { assertIsRollback(MissingRollbackTestCase.class, true); } @Test - public void isRollbackWithEmptyRollback() throws Exception { - assertIsRollback(EmptyRollbackTestCase.class, true); + public void isRollbackWithEmptyMethodLevelRollback() throws Exception { + assertIsRollback(EmptyMethodLevelRollbackTestCase.class, true); } @Test - public void isRollbackWithExplicitValue() throws Exception { - assertIsRollback(RollbackWithExplicitValueTestCase.class, false); + public void isRollbackWithMethodLevelRollbackWithExplicitValue() throws Exception { + assertIsRollback(MethodLevelRollbackWithExplicitValueTestCase.class, false); } @Test - public void isRollbackViaMetaAnnotation() throws Exception { - assertIsRollback(RollbackViaMetaAnnotationTestCase.class, false); + public void isRollbackWithMethodLevelRollbackViaMetaAnnotation() throws Exception { + assertIsRollback(MethodLevelRollbackViaMetaAnnotationTestCase.class, false); + } + + @Test + public void isRollbackWithEmptyClassLevelRollback() throws Exception { + assertIsRollback(EmptyClassLevelRollbackTestCase.class, true); + } + + @Test + public void isRollbackWithClassLevelRollbackWithExplicitValue() throws Exception { + assertIsRollback(ClassLevelRollbackWithExplicitValueTestCase.class, false); + } + + @Test + public void isRollbackWithClassLevelRollbackViaMetaAnnotation() throws Exception { + assertIsRollback(ClassLevelRollbackViaMetaAnnotationTestCase.class, false); + } + + @Test + public void isRollbackWithRollbackAndTransactionConfigurationDeclaredAtClassLevel() throws Exception { + Class clazz = ClassLevelRollbackAndTransactionConfigurationTestCase.class; + BDDMockito.> given(testContext.getTestClass()).willReturn(clazz); + + exception.expect(IllegalStateException.class); + exception.expectMessage(containsString("annotated with both @Rollback and @TransactionConfiguration, but only one is permitted")); + listener.isRollback(testContext); } @@ -260,6 +332,9 @@ public class TransactionalTestExecutionListenerTests { @Retention(RetentionPolicy.RUNTIME) private static @interface MetaTxWithOverride { + @AliasFor(annotation = Transactional.class, attribute = "value") + String transactionManager() default ""; + Propagation propagation() default REQUIRED; } @@ -467,31 +542,76 @@ public class TransactionalTestExecutionListenerTests { static class TransactionConfigurationViaMetaAnnotationWithOverrideTestCase { } + @Transactional + static class EmptyTransactionalTestCase { + } + + @Transactional(transactionManager = "tm") + static class TransactionalWithExplicitQualifierTestCase { + } + + @MetaTransactional + static class TransactionalViaMetaAnnotationTestCase { + } + + @MetaTxWithOverride(transactionManager = "tm") + static class TransactionalViaMetaAnnotationWithExplicitQualifierTestCase { + } + static class MissingRollbackTestCase { public void test() { } } - static class EmptyRollbackTestCase { + static class EmptyMethodLevelRollbackTestCase { @Rollback public void test() { } } - static class RollbackWithExplicitValueTestCase { + static class MethodLevelRollbackWithExplicitValueTestCase { @Rollback(false) public void test() { } } - static class RollbackViaMetaAnnotationTestCase { + static class MethodLevelRollbackViaMetaAnnotationTestCase { @Commit public void test() { } } + @Rollback + @TransactionConfiguration + static class ClassLevelRollbackAndTransactionConfigurationTestCase { + + public void test() { + } + } + + @Rollback + static class EmptyClassLevelRollbackTestCase { + + public void test() { + } + } + + @Rollback(false) + static class ClassLevelRollbackWithExplicitValueTestCase { + + public void test() { + } + } + + @Commit + static class ClassLevelRollbackViaMetaAnnotationTestCase { + + public void test() { + } + } + } diff --git a/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests-context.xml b/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests-context.xml similarity index 93% rename from spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests-context.xml rename to spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests-context.xml index d9663d7c174..ca56b6c107e 100644 --- a/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalSpringRunnerTests-context.xml +++ b/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackFalseTransactionalTests-context.xml @@ -10,6 +10,6 @@ p:data-source-ref="dataSource" /> + class="org.springframework.test.context.junit4.DefaultRollbackFalseTransactionalTests$DatabaseSetup" /> diff --git a/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests-context.xml b/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests-context.xml similarity index 87% rename from spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests-context.xml rename to spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests-context.xml index 1c44b0c01bc..00e3dc647b7 100644 --- a/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalSpringRunnerTests-context.xml +++ b/spring-test/src/test/resources/org/springframework/test/context/junit4/DefaultRollbackTrueTransactionalTests-context.xml @@ -3,6 +3,6 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + class="org.springframework.test.context.junit4.DefaultRollbackTrueTransactionalTests$DatabaseSetup" /> diff --git a/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests-context.xml b/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests-context.xml similarity index 91% rename from spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests-context.xml rename to spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests-context.xml index 44a8ae545cd..07639a63541 100644 --- a/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests-context.xml +++ b/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackFalseTransactionalTests-context.xml @@ -10,6 +10,6 @@ p:data-source-ref="dataSource" /> + class="org.springframework.test.context.junit4.RollbackOverrideDefaultRollbackFalseTransactionalTests$DatabaseSetup" /> diff --git a/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests-context.xml b/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests-context.xml similarity index 84% rename from spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests-context.xml rename to spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests-context.xml index cda53c569e0..f615d952f7a 100644 --- a/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests-context.xml +++ b/spring-test/src/test/resources/org/springframework/test/context/junit4/RollbackOverrideDefaultRollbackTrueTransactionalTests-context.xml @@ -3,6 +3,6 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + class="org.springframework.test.context.junit4.RollbackOverrideDefaultRollbackTrueTransactionalTests$DatabaseSetup" /> diff --git a/spring-test/src/test/resources/org/springframework/test/context/junit4/person-schema.sql b/spring-test/src/test/resources/org/springframework/test/context/junit4/person-schema.sql new file mode 100644 index 00000000000..343d5d4f7ff --- /dev/null +++ b/spring-test/src/test/resources/org/springframework/test/context/junit4/person-schema.sql @@ -0,0 +1 @@ +CREATE TABLE person (name VARCHAR(20) NOT NULL, PRIMARY KEY(name)) \ No newline at end of file diff --git a/src/asciidoc/testing.adoc b/src/asciidoc/testing.adoc index b15f1e081a6..d1e5de81502 100644 --- a/src/asciidoc/testing.adoc +++ b/src/asciidoc/testing.adoc @@ -264,8 +264,7 @@ application context. If you want a transaction to commit -- unusual, but occasionally useful when you want a particular test to populate or modify the database -- the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the -<> and -<> annotations. +<> annotation. See transaction management with the <>. @@ -798,53 +797,22 @@ in conjunction with `@ContextConfiguration`. `@TestExecutionListeners` supports __inherited__ listeners by default. See the javadocs for an example and further details. -* `@TransactionConfiguration` - -+ - -Defines class-level metadata for configuring transactional tests. Specifically, the bean -name of the `PlatformTransactionManager` that should be used to drive transactions can -be explicitly specified if there are multiple beans of type `PlatformTransactionManager` -in the test's `ApplicationContext` and if the bean name of the desired -`PlatformTransactionManager` is not "transactionManager". In addition, you can change -the `defaultRollback` flag to `false`. Typically, `@TransactionConfiguration` is used in -conjunction with `@ContextConfiguration`. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@TransactionConfiguration**(**transactionManager** = "txMgr", **defaultRollback** = false) - public class CustomConfiguredTransactionalTests { - // class body... - } ----- - -+ - -[NOTE] -==== -If the default conventions are sufficient for your test configuration, you can avoid -using `@TransactionConfiguration` altogether. In other words, if you have only one -transaction manager -- or if you have multiple transaction managers but the transaction -manager for tests is named "transactionManager" or specified via a -`TransactionManagementConfigurer` -- and if you want transactions to roll back -automatically, then there is no need to annotate your test class with -`@TransactionConfiguration`. -==== - + * `@Rollback` + -Indicates whether the transaction for the annotated test method should be __rolled +Indicates whether the transaction for a transactional test method should be __rolled back__ after the test method has completed. If `true`, the transaction is rolled back; -otherwise, the transaction is committed. Use `@Rollback` to override the default -rollback flag configured at the class level. +otherwise, the transaction is committed. + ++ + +When declared as a class-level annotation, `@Rollback` defines the default rollback +semantics for all test methods within the test class hierarchy. When declared as a +method-level annotation, `@Rollback` defines rollback semantics for the specific test +method, potentially overriding class-level default rollback semantics. + @@ -1150,7 +1118,6 @@ Each of the following may be used as meta-annotations in conjunction with the * `@Transactional` * `@BeforeTransaction` * `@AfterTransaction` -* `@TransactionConfiguration` * `@Rollback` * `@Sql` * `@SqlConfig` @@ -2398,12 +2365,12 @@ need to override this default, simply provide an alternate path to the you wish to reference a base resource path from the classpath instead of the file system, just use Spring's __classpath:__ prefix. -Please note that Spring's testing support for `WebApplicationContexts` is on par with -its support for standard `ApplicationContexts`. When testing with a -`WebApplicationContext` you are free to declare either XML configuration files or -`@Configuration` classes via `@ContextConfiguration`. You are of course also free to use -any other test annotations such as `@TestExecutionListeners`, -`@TransactionConfiguration`, `@ActiveProfiles`, etc. +Please note that Spring's testing support for `WebApplicationContexts` is on par with its +support for standard `ApplicationContexts`. When testing with a `WebApplicationContext` +you are free to declare XML configuration files, Groovy scripts, or `@Configuration` +classes via `@ContextConfiguration`. You are of course also free to use any other test +annotations such as `@ActiveProfiles`, `@TestExecutionListeners`, `@Sql`, `@Rollback`, +etc. The following examples demonstrate some of the various configuration options for loading a `WebApplicationContext`. @@ -3150,9 +3117,8 @@ See <> for an additional example. By default, test transactions will be automatically rolled back after completion of the test; however, transactional commit and rollback behavior can be configured declaratively -via the class-level `@TransactionConfiguration` and method-level `@Rollback` annotations. -See the corresponding entries in the <> section for further details. +via the `@Rollback` annotation. See the corresponding entry in the +<> section for further details. [[testcontext-tx-programmatic-tx-mgt]] ===== Programmatic transaction management @@ -3224,14 +3190,12 @@ to run within a transaction. `TransactionalTestExecutionListener` expects a `PlatformTransactionManager` bean to be defined in the Spring `ApplicationContext` for the test. In case there are multiple -instances of `PlatformTransactionManager` within the test's `ApplicationContext`, -`@TransactionConfiguration` supports configuring the bean name of the -`PlatformTransactionManager` that should be used to drive transactions. Alternatively, a -_qualifier_ may be declared via `@Transactional("myQualifier")`, or -`TransactionManagementConfigurer` can be implemented by an `@Configuration` class. -Consult the javadocs for `TestContextTransactionUtils.retrieveTransactionManager()` for -details on the algorithm used to look up a transaction manager in the test's -`ApplicationContext`. +instances of `PlatformTransactionManager` within the test's `ApplicationContext`, a +_qualifier_ may be declared via `@Transactional("myTxMgr")` or +`@Transactional(transactionManager = "myTxMgr")`, or `TransactionManagementConfigurer` +can be implemented by an `@Configuration` class. Consult the javadocs for +`TestContextTransactionUtils.retrieveTransactionManager()` for details on the algorithm +used to look up a transaction manager in the test's `ApplicationContext`. [[testcontext-tx-annotation-demo]] ===== Demonstration of all transaction-related annotations @@ -3249,8 +3213,8 @@ declarative SQL script execution with default transaction rollback semantics. ---- @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration - **@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false) - @Transactional** + @Transactional(transactionManager = "txMgr") + **@Rollback(false)** public class FictitiousTransactionalTest { **@BeforeTransaction** @@ -3264,7 +3228,7 @@ declarative SQL script execution with default transaction rollback semantics. } @Test - // overrides the class-level defaultRollback setting + // overrides the class-level default rollback setting **@Rollback(true)** public void modifyDatabaseWithinTransaction() { // logic which uses the test data and modifies database state diff --git a/src/asciidoc/whats-new.adoc b/src/asciidoc/whats-new.adoc index 09834a8977b..9e4c6a39b1c 100644 --- a/src/asciidoc/whats-new.adoc +++ b/src/asciidoc/whats-new.adoc @@ -577,6 +577,9 @@ public @interface MyTestConfig { _before_ a test -- for example, if some rogue (i.e., yet to be determined) test within a large test suite has corrupted the original configuration for the `ApplicationContext`. +* `@Rollback` may now be used to configure class-level _default rollback_ semantics. +** Consequently, `@TransactionConfiguration` is now deprecated and will be removed in a + subsequent release. * `@Sql` now supports execution of _inlined SQL statements_ via a new `statements` attribute. * The `ContextCache` that is used for caching ++ApplicationContext++s