Concurrency and exception message refinements for test transactions
This commit is contained in:
@@ -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,6 +53,42 @@ import static org.junit.Assert.*;
|
||||
@DirtiesContext
|
||||
public class PrimaryTransactionManagerTests {
|
||||
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource1) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource1);
|
||||
}
|
||||
|
||||
|
||||
@BeforeTransaction
|
||||
public void beforeTransaction() {
|
||||
assertNumUsers(0);
|
||||
}
|
||||
|
||||
@AfterTransaction
|
||||
public void afterTransaction() {
|
||||
assertNumUsers(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
TransactionTestUtils.assertInTransaction(true);
|
||||
|
||||
ClassPathResource resource = new ClassPathResource("/org/springframework/test/context/jdbc/data.sql");
|
||||
new ResourceDatabasePopulator(resource).execute(jdbcTemplate.getDataSource());
|
||||
|
||||
assertNumUsers(1);
|
||||
}
|
||||
|
||||
private void assertNumUsers(int expected) {
|
||||
assertEquals("Number of rows in the 'user' table", expected,
|
||||
JdbcTestUtils.countRowsInTable(this.jdbcTemplate, "user"));
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@@ -69,54 +105,16 @@ public class PrimaryTransactionManagerTests {
|
||||
|
||||
@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;
|
||||
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource1) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource1);
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void beforeTransaction() {
|
||||
assertNumUsers(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
TransactionTestUtils.assertInTransaction(true);
|
||||
|
||||
ClassPathResource resource = new ClassPathResource("/org/springframework/test/context/jdbc/data.sql");
|
||||
new ResourceDatabasePopulator(resource).execute(jdbcTemplate.getDataSource());
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.mockito.BDDMockito;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.test.annotation.Commit;
|
||||
@@ -51,7 +51,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;
|
||||
@@ -64,100 +63,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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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 assertIsRollback(Class<?> clazz, boolean rollback) throws NoSuchMethodException, Exception {
|
||||
BDDMockito.<Class<?>> 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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
given(testContext.getTestInstance()).willReturn(instance);
|
||||
@@ -172,7 +92,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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +111,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
|
||||
@@ -199,7 +119,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);
|
||||
}
|
||||
|
||||
@@ -289,11 +209,84 @@ 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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
Invocable instance = BeanUtils.instantiateClass(clazz);
|
||||
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 assertIsRollback(Class<?> clazz, boolean rollback) throws Exception {
|
||||
BDDMockito.<Class<?>> 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
|
||||
@@ -308,12 +301,12 @@ 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 {
|
||||
}
|
||||
|
||||
private interface Invocable {
|
||||
@@ -348,7 +341,6 @@ public class TransactionalTestExecutionListenerTests {
|
||||
}
|
||||
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,11 +353,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,7 +368,6 @@ public class TransactionalTestExecutionListenerTests {
|
||||
}
|
||||
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,11 +380,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@MetaTransactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +395,6 @@ public class TransactionalTestExecutionListenerTests {
|
||||
}
|
||||
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,11 +407,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@MetaTxWithOverride(propagation = NOT_SUPPORTED)
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,11 +422,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,11 +437,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,11 +452,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,11 +467,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,11 +494,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,11 +505,9 @@ public class TransactionalTestExecutionListenerTests {
|
||||
|
||||
@Transactional
|
||||
public void transactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
public void nonTransactionalTest() {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user