diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/AfterTransaction.java b/spring-test/src/main/java/org/springframework/test/context/transaction/AfterTransaction.java
index a7f6653e886..b740509c567 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/AfterTransaction.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/AfterTransaction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -28,15 +28,15 @@ import java.lang.annotation.Target;
* configured to run within a transaction via Spring's {@code @Transactional}
* annotation.
*
- *
As of Spring Framework 4.3, {@code @AfterTransaction} may be declared on
- * Java 8 based interface default methods.
- *
*
{@code @AfterTransaction} methods declared in superclasses or as interface
* default methods will be executed after those of the current test class.
*
*
As of Spring Framework 4.0, this annotation may be used as a
* meta-annotation to create custom composed annotations.
*
+ *
As of Spring Framework 4.3, {@code @AfterTransaction} may also be
+ * declared on Java 8 based interface default methods.
+ *
* @author Sam Brannen
* @since 2.5
* @see org.springframework.transaction.annotation.Transactional
diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/BeforeTransaction.java b/spring-test/src/main/java/org/springframework/test/context/transaction/BeforeTransaction.java
index 217c7d1768b..c13fa66c8a9 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/BeforeTransaction.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/BeforeTransaction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -28,15 +28,15 @@ import java.lang.annotation.Target;
* configured to run within a transaction via Spring's {@code @Transactional}
* annotation.
*
- *
As of Spring Framework 4.3, {@code @BeforeTransaction} may be declared on
- * Java 8 based interface default methods.
- *
*
{@code @BeforeTransaction} methods declared in superclasses or as interface
* default methods will be executed before those of the current test class.
*
*
As of Spring Framework 4.0, this annotation may be used as a
* meta-annotation to create custom composed annotations.
*
+ *
As of Spring Framework 4.3, {@code @BeforeTransaction} may also be
+ * declared on Java 8 based interface default methods.
+ *
* @author Sam Brannen
* @since 2.5
* @see org.springframework.transaction.annotation.Transactional
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 dd7fe45022e..77c1b2b7c18 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-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -38,6 +38,7 @@ 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.
*
* @author Sam Brannen
@@ -46,8 +47,6 @@ import org.springframework.util.StringUtils;
*/
public abstract class TestContextTransactionUtils {
- private static final Log logger = LogFactory.getLog(TestContextTransactionUtils.class);
-
/**
* Default bean name for a {@link DataSource}: {@code "dataSource"}.
*/
@@ -60,9 +59,8 @@ public abstract class TestContextTransactionUtils {
public static final String DEFAULT_TRANSACTION_MANAGER_NAME = "transactionManager";
- private TestContextTransactionUtils() {
- /* prevent instantiation */
- }
+ private static final Log logger = LogFactory.getLog(TestContextTransactionUtils.class);
+
/**
* Retrieve the {@link DataSource} to use for the supplied {@linkplain TestContext
@@ -80,8 +78,8 @@ public abstract class TestContextTransactionUtils {
* {@linkplain #DEFAULT_DATA_SOURCE_NAME default data source name}.
* @param testContext the test context for which the {@code DataSource}
* should be retrieved; never {@code null}
- * @param name the name of the {@code DataSource} to retrieve; may be {@code null}
- * or empty
+ * @param name the name of the {@code DataSource} to retrieve
+ * (may be {@code null} or empty)
* @return the {@code DataSource} to use, or {@code null} if not found
* @throws BeansException if an error occurs while retrieving an explicitly
* named {@code DataSource}
@@ -91,14 +89,14 @@ public abstract class TestContextTransactionUtils {
BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
try {
- // look up by type and explicit name
+ // Look up by type and explicit name
if (StringUtils.hasText(name)) {
return bf.getBean(name, DataSource.class);
}
}
catch (BeansException ex) {
- logger.error(
- String.format("Failed to retrieve DataSource named '%s' for test context %s", name, testContext), ex);
+ logger.error(String.format("Failed to retrieve DataSource named '%s' for test context %s",
+ name, testContext), ex);
throw ex;
}
@@ -106,9 +104,9 @@ public abstract class TestContextTransactionUtils {
if (bf instanceof ListableBeanFactory) {
ListableBeanFactory lbf = (ListableBeanFactory) bf;
- // look up single bean by type
- Map dataSources = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf,
- DataSource.class);
+ // Look up single bean by type
+ Map dataSources =
+ BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, DataSource.class);
if (dataSources.size() == 1) {
return dataSources.values().iterator().next();
}
@@ -150,8 +148,8 @@ public abstract class TestContextTransactionUtils {
* name}.
* @param testContext the test context for which the transaction manager
* should be retrieved; never {@code null}
- * @param name the name of the transaction manager to retrieve; may be
- * {@code null} or empty
+ * @param name the name of the transaction manager to retrieve
+ * (may be {@code null} or empty)
* @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
@@ -163,14 +161,14 @@ public abstract class TestContextTransactionUtils {
BeanFactory bf = testContext.getApplicationContext().getAutowireCapableBeanFactory();
try {
- // look up by type and explicit name
+ // Look up by type and explicit name
if (StringUtils.hasText(name)) {
return bf.getBean(name, PlatformTransactionManager.class);
}
}
catch (BeansException ex) {
- logger.error(String.format("Failed to retrieve transaction manager named '%s' for test context %s", name,
- testContext), ex);
+ logger.error(String.format("Failed to retrieve transaction manager named '%s' for test context %s",
+ name, testContext), ex);
throw ex;
}
@@ -178,28 +176,26 @@ public abstract class TestContextTransactionUtils {
if (bf instanceof ListableBeanFactory) {
ListableBeanFactory lbf = (ListableBeanFactory) bf;
- // look up single bean by type
- Map txMgrs = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf,
- PlatformTransactionManager.class);
+ // Look up single bean by type
+ Map txMgrs =
+ BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, PlatformTransactionManager.class);
if (txMgrs.size() == 1) {
return txMgrs.values().iterator().next();
}
try {
- // look up single bean by type, with support for 'primary' beans
+ // Look up single bean by type, with support for 'primary' beans
return bf.getBean(PlatformTransactionManager.class);
}
catch (BeansException ex) {
logBeansException(testContext, ex, PlatformTransactionManager.class);
}
- // look up single TransactionManagementConfigurer
- Map configurers = BeanFactoryUtils.beansOfTypeIncludingAncestors(
- lbf, TransactionManagementConfigurer.class);
- if (configurers.size() > 1) {
- throw new IllegalStateException(
+ // Look up single TransactionManagementConfigurer
+ Map configurers =
+ BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, TransactionManagementConfigurer.class);
+ Assert.state(configurers.size() <= 1,
"Only one TransactionManagementConfigurer may exist in the ApplicationContext");
- }
if (configurers.size() == 1) {
return configurers.values().iterator().next().annotationDrivenTransactionManager();
}
@@ -225,13 +221,13 @@ public abstract class TestContextTransactionUtils {
* Create a delegating {@link TransactionAttribute} for the supplied target
* {@link TransactionAttribute} and {@link TestContext}, using the names of
* the test class and test method to build the name of the transaction.
- *
- * @param testContext the {@code TestContext} upon which to base the name; never {@code null}
- * @param targetAttribute the {@code TransactionAttribute} to delegate to; never {@code null}
+ * @param testContext the {@code TestContext} upon which to base the name
+ * @param targetAttribute the {@code TransactionAttribute} to delegate to
* @return the delegating {@code TransactionAttribute}
*/
- public static TransactionAttribute createDelegatingTransactionAttribute(TestContext testContext,
- TransactionAttribute targetAttribute) {
+ public static TransactionAttribute createDelegatingTransactionAttribute(
+ TestContext testContext, TransactionAttribute targetAttribute) {
+
Assert.notNull(testContext, "TestContext must not be null");
Assert.notNull(targetAttribute, "Target TransactionAttribute must not be null");
return new TestContextTransactionAttribute(targetAttribute, testContext);
diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TestTransaction.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TestTransaction.java
index 427e0b7d336..d238ed800fe 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/TestTransaction.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TestTransaction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -18,6 +18,7 @@ package org.springframework.test.context.transaction;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.Assert;
/**
* {@code TestTransaction} provides a collection of static utility methods for
@@ -49,10 +50,8 @@ public class TestTransaction {
TransactionContext transactionContext = TransactionContextHolder.getCurrentTransactionContext();
if (transactionContext != null) {
TransactionStatus transactionStatus = transactionContext.getTransactionStatus();
- return (transactionStatus != null) && (!transactionStatus.isCompleted());
+ return (transactionStatus != null && !transactionStatus.isCompleted());
}
-
- // else
return false;
}
@@ -79,8 +78,7 @@ public class TestTransaction {
* Rather, the value of this flag will be used to determine whether or not
* the current test-managed transaction should be rolled back or committed
* once it is {@linkplain #end ended}.
- * @throws IllegalStateException if a transaction is not active for the
- * current test
+ * @throws IllegalStateException if no transaction is active for the current test
* @see #isActive()
* @see #isFlaggedForRollback()
* @see #start()
@@ -96,8 +94,7 @@ public class TestTransaction {
* Rather, the value of this flag will be used to determine whether or not
* the current test-managed transaction should be rolled back or committed
* once it is {@linkplain #end ended}.
- * @throws IllegalStateException if a transaction is not active for the
- * current test
+ * @throws IllegalStateException if no transaction is active for the current test
* @see #isActive()
* @see #isFlaggedForRollback()
* @see #start()
@@ -121,9 +118,9 @@ public class TestTransaction {
}
/**
- * Immediately force a commit or rollback of the current
- * test-managed transaction, according to the {@linkplain #isFlaggedForRollback
- * rollback flag}.
+ * Immediately force a commit or rollback of the
+ * current test-managed transaction, according to the
+ * {@linkplain #isFlaggedForRollback rollback flag}.
* @throws IllegalStateException if the transaction context could not be
* retrieved or if a transaction is not active for the current test
* @see #isActive()
@@ -133,11 +130,10 @@ public class TestTransaction {
requireCurrentTransactionContext().endTransaction();
}
+
private static TransactionContext requireCurrentTransactionContext() {
TransactionContext txContext = TransactionContextHolder.getCurrentTransactionContext();
- if (txContext == null) {
- throw new IllegalStateException("TransactionContext is not active");
- }
+ Assert.state(txContext != null, "TransactionContext is not active");
return txContext;
}
@@ -145,4 +141,4 @@ public class TestTransaction {
requireCurrentTransactionContext().setFlaggedForRollback(flag);
}
-}
\ No newline at end of file
+}
diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContext.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContext.java
index 0319dbdb8e1..bebcb4590da 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContext.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -16,6 +16,8 @@
package org.springframework.test.context.transaction;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -24,6 +26,7 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.Assert;
/**
* Transaction context for a specific {@link TestContext}.
@@ -50,7 +53,7 @@ class TransactionContext {
private TransactionStatus transactionStatus;
- private volatile int transactionsStarted = 0;
+ private final AtomicInteger transactionsStarted = new AtomicInteger(0);
TransactionContext(TestContext testContext, PlatformTransactionManager transactionManager,
@@ -79,32 +82,30 @@ class TransactionContext {
void setFlaggedForRollback(boolean flaggedForRollback) {
if (this.transactionStatus == null) {
- throw new IllegalStateException(String.format(
- "Failed to set rollback flag for test context %s: transaction does not exist.", this.testContext));
+ throw new IllegalStateException(
+ "Failed to set rollback flag - transaction does not exist: " + this.testContext);
}
this.flaggedForRollback = flaggedForRollback;
}
/**
- * Start a new transaction for the configured {@linkplain #getTestContext test context}.
+ * Start a new transaction for the configured test context.
* Only call this method if {@link #endTransaction} has been called or if no
* transaction has been previously started.
* @throws TransactionException if starting the transaction fails
*/
void startTransaction() {
- if (this.transactionStatus != null) {
- throw new IllegalStateException(
- "Cannot start a new transaction without ending the existing transaction first.");
- }
+ Assert.state(this.transactionStatus == null,
+ "Cannot start a new transaction without ending the existing transaction first");
this.flaggedForRollback = this.defaultRollback;
this.transactionStatus = this.transactionManager.getTransaction(this.transactionDefinition);
- ++this.transactionsStarted;
+ int transactionsStarted = this.transactionsStarted.incrementAndGet();
if (logger.isInfoEnabled()) {
logger.info(String.format(
"Began transaction (%s) for test context %s; transaction manager [%s]; rollback [%s]",
- this.transactionsStarted, this.testContext, this.transactionManager, flaggedForRollback));
+ transactionsStarted, this.testContext, this.transactionManager, flaggedForRollback));
}
}
@@ -119,8 +120,8 @@ class TransactionContext {
this.testContext, this.transactionStatus, this.flaggedForRollback));
}
if (this.transactionStatus == null) {
- throw new IllegalStateException(String.format(
- "Failed to end transaction for test context %s: transaction does not exist.", this.testContext));
+ throw new IllegalStateException(
+ "Failed to end transaction - transaction does not exist: " + this.testContext);
}
try {
@@ -136,8 +137,8 @@ class TransactionContext {
}
if (logger.isInfoEnabled()) {
- logger.info(String.format("%s transaction for test context %s.",
- (this.flaggedForRollback ? "Rolled back" : "Committed"), this.testContext));
+ logger.info((this.flaggedForRollback ? "Rolled back" : "Committed") +
+ " transaction for test: " + this.testContext);
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContextHolder.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContextHolder.java
index 6cc004ea974..ef906e0c0fa 100644
--- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContextHolder.java
+++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionContextHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -39,11 +39,9 @@ class TransactionContextHolder {
}
static TransactionContext removeCurrentTransactionContext() {
- synchronized (currentTransactionContext) {
- TransactionContext transactionContext = currentTransactionContext.get();
- currentTransactionContext.remove();
- return transactionContext;
- }
+ TransactionContext transactionContext = currentTransactionContext.get();
+ currentTransactionContext.remove();
+ return transactionContext;
}
}
\ No newline at end of file
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 356eb3d053e..9227a1a907e 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -163,14 +163,12 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
*/
@Override
public void beforeTestMethod(final TestContext testContext) throws Exception {
- final Method testMethod = testContext.getTestMethod();
- final Class> testClass = testContext.getTestClass();
- Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null");
+ Method testMethod = testContext.getTestMethod();
+ Class> testClass = testContext.getTestClass();
+ Assert.notNull(testMethod, "Test method of supplied TestContext must not be null");
TransactionContext txContext = TransactionContextHolder.removeCurrentTransactionContext();
- if (txContext != null) {
- throw new IllegalStateException("Cannot start a new transaction without ending the existing transaction.");
- }
+ Assert.state(txContext == null, "Cannot start new transaction without ending existing transaction");
PlatformTransactionManager tm = null;
TransactionAttribute transactionAttribute = this.attributeSource.getTransactionAttribute(testMethod, testClass);
@@ -180,8 +178,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
transactionAttribute);
if (logger.isDebugEnabled()) {
- logger.debug("Explicit transaction definition [" + transactionAttribute + "] found for test context " +
- testContext);
+ logger.debug("Explicit transaction definition [" + transactionAttribute +
+ "] found for test context " + testContext);
}
if (transactionAttribute.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
@@ -191,9 +189,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
tm = getTransactionManager(testContext, transactionAttribute.getQualifier());
if (tm == null) {
- throw new IllegalStateException(String.format(
- "Failed to retrieve PlatformTransactionManager for @Transactional test for test context %s.",
- testContext));
+ throw new IllegalStateException(
+ "Failed to retrieve PlatformTransactionManager for @Transactional test: " + testContext);
}
}
@@ -223,7 +220,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
TransactionStatus transactionStatus = txContext.getTransactionStatus();
try {
// If the transaction is still active...
- if ((transactionStatus != null) && !transactionStatus.isCompleted()) {
+ if (transactionStatus != null && !transactionStatus.isCompleted()) {
txContext.endTransaction();
}
}
@@ -380,15 +377,15 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
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()));
+ 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()));
+ logger.debug(String.format("Retrieved default @Rollback(%s) for test class [%s].",
+ defaultRollback, testClass.getName()));
}
return defaultRollback;
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java
index d9cd1526793..dabedc902eb 100644
--- a/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/transaction/PrimaryTransactionManagerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -53,38 +53,6 @@ import static org.junit.Assert.*;
@DirtiesContext
public class PrimaryTransactionManagerTests {
- @Configuration
- static class Config {
-
- @Primary
- @Bean
- public PlatformTransactionManager primaryTransactionManager() {
- return new DataSourceTransactionManager(dataSource1());
- }
-
- @Bean
- public PlatformTransactionManager additionalTransactionManager() {
- return new DataSourceTransactionManager(dataSource2());
- }
-
- @Bean
- public DataSource dataSource1() {
- // @formatter:off
- return new EmbeddedDatabaseBuilder()
- .generateUniqueName(true)
- .addScript("classpath:/org/springframework/test/context/jdbc/schema.sql")
- .build();
- // @formatter:on
- }
-
- @Bean
- public DataSource dataSource2() {
- return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
- }
-
- }
-
-
private JdbcTemplate jdbcTemplate;
@@ -93,11 +61,17 @@ public class PrimaryTransactionManagerTests {
this.jdbcTemplate = new JdbcTemplate(dataSource1);
}
+
@BeforeTransaction
public void beforeTransaction() {
assertNumUsers(0);
}
+ @AfterTransaction
+ public void afterTransaction() {
+ assertNumUsers(0);
+ }
+
@Test
@Transactional
public void transactionalTest() {
@@ -109,14 +83,38 @@ public class PrimaryTransactionManagerTests {
assertNumUsers(1);
}
- @AfterTransaction
- public void afterTransaction() {
- assertNumUsers(0);
+ private void assertNumUsers(int expected) {
+ assertEquals("Number of rows in the 'user' table", expected,
+ JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user"));
}
- private void assertNumUsers(int expected) {
- assertEquals("Number of rows in the 'user' table.", expected,
- JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user"));
+
+ @Configuration
+ static class Config {
+
+ @Primary
+ @Bean
+ public PlatformTransactionManager primaryTransactionManager() {
+ return new DataSourceTransactionManager(dataSource1());
+ }
+
+ @Bean
+ public PlatformTransactionManager additionalTransactionManager() {
+ return new DataSourceTransactionManager(dataSource2());
+ }
+
+ @Bean
+ public DataSource dataSource1() {
+ return new EmbeddedDatabaseBuilder()
+ .generateUniqueName(true)
+ .addScript("classpath:/org/springframework/test/context/jdbc/schema.sql")
+ .build();
+ }
+
+ @Bean
+ public DataSource dataSource2() {
+ return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
+ }
}
}
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 82cb00816e1..e53d0e8c895 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-2016 the original author or authors.
+ * Copyright 2002-2018 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.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-
import org.mockito.BDDMockito;
import org.springframework.core.annotation.AliasFor;
@@ -53,7 +52,6 @@ public class TransactionalTestExecutionListenerTests {
private final PlatformTransactionManager tm = mock(PlatformTransactionManager.class);
private final TransactionalTestExecutionListener listener = new TransactionalTestExecutionListener() {
-
@Override
protected PlatformTransactionManager getTransactionManager(TestContext testContext, String qualifier) {
return tm;
@@ -66,110 +64,21 @@ public class TransactionalTestExecutionListenerTests {
public ExpectedException exception = ExpectedException.none();
- private void assertBeforeTestMethod(Class extends Invocable> clazz) throws Exception {
- assertBeforeTestMethodWithTransactionalTestMethod(clazz);
- assertBeforeTestMethodWithNonTransactionalTestMethod(clazz);
- }
-
- private void assertBeforeTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
- assertBeforeTestMethodWithTransactionalTestMethod(clazz, true);
- }
-
- private void assertBeforeTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz, boolean invokedInTx)
- throws Exception {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
- Invocable instance = clazz.newInstance();
- given(testContext.getTestInstance()).willReturn(instance);
- given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest"));
-
- assertFalse("callback should not have been invoked", instance.invoked());
- TransactionContextHolder.removeCurrentTransactionContext();
- listener.beforeTestMethod(testContext);
- assertEquals(invokedInTx, instance.invoked());
- }
-
- private void assertBeforeTestMethodWithNonTransactionalTestMethod(Class extends Invocable> clazz)
- throws Exception {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
- Invocable instance = clazz.newInstance();
- given(testContext.getTestInstance()).willReturn(instance);
- given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest"));
-
- assertFalse("callback should not have been invoked", instance.invoked());
- TransactionContextHolder.removeCurrentTransactionContext();
- listener.beforeTestMethod(testContext);
- assertFalse("callback should not have been invoked", instance.invoked());
- }
-
- private void assertAfterTestMethod(Class extends Invocable> clazz) throws Exception {
- assertAfterTestMethodWithTransactionalTestMethod(clazz);
- assertAfterTestMethodWithNonTransactionalTestMethod(clazz);
- }
-
- private void assertAfterTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
- Invocable instance = clazz.newInstance();
- given(testContext.getTestInstance()).willReturn(instance);
- given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest"));
-
- given(tm.getTransaction(BDDMockito.any(TransactionDefinition.class))).willReturn(new SimpleTransactionStatus());
-
- assertFalse("callback should not have been invoked", instance.invoked());
- TransactionContextHolder.removeCurrentTransactionContext();
- listener.beforeTestMethod(testContext);
- assertFalse("callback should not have been invoked", instance.invoked());
- listener.afterTestMethod(testContext);
- assertTrue("callback should have been invoked", instance.invoked());
- }
-
- private void assertAfterTestMethodWithNonTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
- Invocable instance = clazz.newInstance();
- given(testContext.getTestInstance()).willReturn(instance);
- given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest"));
-
- assertFalse("callback should not have been invoked", instance.invoked());
- TransactionContextHolder.removeCurrentTransactionContext();
- listener.beforeTestMethod(testContext);
- listener.afterTestMethod(testContext);
- assertFalse("callback should not have been invoked", instance.invoked());
- }
-
- private void assertTransactionConfigurationAttributes(Class> clazz, String transactionManagerName,
- boolean defaultRollback) {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
-
- TransactionConfigurationAttributes attributes = listener.retrieveConfigurationAttributes(testContext);
- assertNotNull(attributes);
- assertEquals(transactionManagerName, attributes.getTransactionManagerName());
- assertEquals(defaultRollback, attributes.isDefaultRollback());
- }
-
- private void assertIsRollback(Class> clazz, boolean rollback) throws NoSuchMethodException, Exception {
- BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
- given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
- assertEquals(rollback, listener.isRollback(testContext));
- }
-
@After
public void cleanUpThreadLocalStateForSubsequentTestClassesInSuite() {
TransactionContextHolder.removeCurrentTransactionContext();
}
- /**
- * SPR-13895
- */
- @Test
+
+ @Test // SPR-13895
public void transactionalTestWithoutTransactionManager() throws Exception {
TransactionalTestExecutionListener listener = new TransactionalTestExecutionListener() {
-
protected PlatformTransactionManager getTransactionManager(TestContext testContext, String qualifier) {
return null;
}
};
Class extends Invocable> clazz = TransactionalDeclaredOnClassLocallyTestCase.class;
-
BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
Invocable instance = clazz.newInstance();
given(testContext.getTestInstance()).willReturn(instance);
@@ -184,7 +93,7 @@ public class TransactionalTestExecutionListenerTests {
}
catch (IllegalStateException e) {
assertTrue(e.getMessage().startsWith(
- "Failed to retrieve PlatformTransactionManager for @Transactional test for test context"));
+ "Failed to retrieve PlatformTransactionManager for @Transactional test"));
}
}
@@ -203,7 +112,7 @@ public class TransactionalTestExecutionListenerTests {
// Note: not actually invoked within a transaction since the test class is
// annotated with @MetaTxWithOverride(propagation = NOT_SUPPORTED)
assertBeforeTestMethodWithTransactionalTestMethod(
- TransactionalDeclaredOnClassViaMetaAnnotationWithOverrideTestCase.class, false);
+ TransactionalDeclaredOnClassViaMetaAnnotationWithOverrideTestCase.class, false);
}
@Test
@@ -211,7 +120,7 @@ public class TransactionalTestExecutionListenerTests {
// Note: not actually invoked within a transaction since the method is
// annotated with @MetaTxWithOverride(propagation = NOT_SUPPORTED)
assertBeforeTestMethodWithTransactionalTestMethod(
- TransactionalDeclaredOnMethodViaMetaAnnotationWithOverrideTestCase.class, false);
+ TransactionalDeclaredOnMethodViaMetaAnnotationWithOverrideTestCase.class, false);
assertBeforeTestMethodWithNonTransactionalTestMethod(TransactionalDeclaredOnMethodViaMetaAnnotationWithOverrideTestCase.class);
}
@@ -315,8 +224,7 @@ public class TransactionalTestExecutionListenerTests {
// @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);
+ assertTransactionConfigurationAttributes(TransactionalViaMetaAnnotationWithExplicitQualifierTestCase.class, "", true);
}
@Test
@@ -375,11 +283,95 @@ public class TransactionalTestExecutionListenerTests {
}
- // -------------------------------------------------------------------------
+ private void assertBeforeTestMethod(Class extends Invocable> clazz) throws Exception {
+ assertBeforeTestMethodWithTransactionalTestMethod(clazz);
+ assertBeforeTestMethodWithNonTransactionalTestMethod(clazz);
+ }
+
+ private void assertBeforeTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
+ assertBeforeTestMethodWithTransactionalTestMethod(clazz, true);
+ }
+
+ private void assertBeforeTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz, boolean invokedInTx)
+ throws Exception {
+
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ Invocable instance = clazz.newInstance();
+ given(testContext.getTestInstance()).willReturn(instance);
+ given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest"));
+
+ assertFalse("callback should not have been invoked", instance.invoked());
+ TransactionContextHolder.removeCurrentTransactionContext();
+ listener.beforeTestMethod(testContext);
+ assertEquals(invokedInTx, instance.invoked());
+ }
+
+ private void assertBeforeTestMethodWithNonTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ Invocable instance = clazz.newInstance();
+ given(testContext.getTestInstance()).willReturn(instance);
+ given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest"));
+
+ assertFalse("callback should not have been invoked", instance.invoked());
+ TransactionContextHolder.removeCurrentTransactionContext();
+ listener.beforeTestMethod(testContext);
+ assertFalse("callback should not have been invoked", instance.invoked());
+ }
+
+ private void assertAfterTestMethod(Class extends Invocable> clazz) throws Exception {
+ assertAfterTestMethodWithTransactionalTestMethod(clazz);
+ assertAfterTestMethodWithNonTransactionalTestMethod(clazz);
+ }
+
+ private void assertAfterTestMethodWithTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ Invocable instance = clazz.newInstance();
+ given(testContext.getTestInstance()).willReturn(instance);
+ given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("transactionalTest"));
+ given(tm.getTransaction(BDDMockito.any(TransactionDefinition.class))).willReturn(new SimpleTransactionStatus());
+
+ assertFalse("callback should not have been invoked", instance.invoked());
+ TransactionContextHolder.removeCurrentTransactionContext();
+ listener.beforeTestMethod(testContext);
+ assertFalse("callback should not have been invoked", instance.invoked());
+ listener.afterTestMethod(testContext);
+ assertTrue("callback should have been invoked", instance.invoked());
+ }
+
+ private void assertAfterTestMethodWithNonTransactionalTestMethod(Class extends Invocable> clazz) throws Exception {
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ Invocable instance = clazz.newInstance();
+ given(testContext.getTestInstance()).willReturn(instance);
+ given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("nonTransactionalTest"));
+
+ assertFalse("callback should not have been invoked", instance.invoked());
+ TransactionContextHolder.removeCurrentTransactionContext();
+ listener.beforeTestMethod(testContext);
+ listener.afterTestMethod(testContext);
+ assertFalse("callback should not have been invoked", instance.invoked());
+ }
+
+ private void assertTransactionConfigurationAttributes(
+ Class> clazz, String transactionManagerName, boolean defaultRollback) {
+
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ TransactionConfigurationAttributes attributes = listener.retrieveConfigurationAttributes(testContext);
+
+ assertNotNull(attributes);
+ assertEquals(transactionManagerName, attributes.getTransactionManagerName());
+ assertEquals(defaultRollback, attributes.isDefaultRollback());
+ }
+
+ private void assertIsRollback(Class> clazz, boolean rollback) throws NoSuchMethodException, Exception {
+ BDDMockito.> given(testContext.getTestClass()).willReturn(clazz);
+ given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
+ assertEquals(rollback, listener.isRollback(testContext));
+ }
+
@Transactional
@Retention(RetentionPolicy.RUNTIME)
- private static @interface MetaTransactional {
+ private @interface MetaTransactional {
}
@Transactional
@@ -394,17 +386,17 @@ public class TransactionalTestExecutionListenerTests {
@BeforeTransaction
@Retention(RetentionPolicy.RUNTIME)
- private static @interface MetaBeforeTransaction {
+ private @interface MetaBeforeTransaction {
}
@AfterTransaction
@Retention(RetentionPolicy.RUNTIME)
- private static @interface MetaAfterTransaction {
+ private @interface MetaAfterTransaction {
}
@TransactionConfiguration
@Retention(RetentionPolicy.RUNTIME)
- private static @interface MetaTxConfig {
+ private @interface MetaTxConfig {
String transactionManager() default "metaTxMgr";
}
@@ -441,7 +433,6 @@ public class TransactionalTestExecutionListenerTests {
}
public void transactionalTest() {
- /* no-op */
}
}
@@ -454,11 +445,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -471,7 +460,6 @@ public class TransactionalTestExecutionListenerTests {
}
public void transactionalTest() {
- /* no-op */
}
}
@@ -484,11 +472,9 @@ public class TransactionalTestExecutionListenerTests {
@MetaTransactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -501,7 +487,6 @@ public class TransactionalTestExecutionListenerTests {
}
public void transactionalTest() {
- /* no-op */
}
}
@@ -514,11 +499,9 @@ public class TransactionalTestExecutionListenerTests {
@MetaTxWithOverride(propagation = NOT_SUPPORTED)
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -531,11 +514,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -548,11 +529,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -565,11 +544,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -582,11 +559,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -611,11 +586,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}
@@ -624,11 +597,9 @@ public class TransactionalTestExecutionListenerTests {
@Transactional
public void transactionalTest() {
- /* no-op */
}
public void nonTransactionalTest() {
- /* no-op */
}
}