我尝试使用DbUnit + Spring(4.1.1)测试+ MyBatis + Oracle
来实现集成测试我正在做以下事情:
问题是嵌套事务没有回滚。如果方法A插入数据,则方法B会看到该数据。
可能是JDBC(11.2.0.1.0)驱动程序问题(因为spring使用Savepoint方法)还是Oracle(11g)?
我已附加简化(一体化)测试以证明此问题:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/core-dao-config.xml", "/test-context.xml" })
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionTest.class, TransactionalTestExecutionListener.class})
@Transactional(propagation = Propagation.NESTED)
public class TransactionTest extends AbstractTestExecutionListener
{
public TransactionTest(){}
DataSource dataSource;
DataSourceTransactionManager txManager;
protected void injectDependencies(final TestContext testContext) throws Exception {
dataSource = testContext.getApplicationContext().getBean(DataSource.class);
txManager = testContext.getApplicationContext().getBean(DataSourceTransactionManager.class);
}
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
injectDependencies(testContext);
final TransactionStatus transaction = txManager.getTransaction(new DefaultTransactionAttribute());
testContext.setAttribute("parenttx", transaction);
}
@Autowired
SomeDao someDao;
@Test
public void testTx() {
final DbObject domainObject = new DbObject();
domainObject.setKey(-303L);
someDao.add(domainObject);
assertNotNull(someDao.findByKey(-303L));
}
@Test
public void testInserted() {
assertNull(someDao.findByKey(-303L));
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
final TransactionStatus parenttx =(TransactionStatus)testContext.getAttribute("parenttx");
Validate.notNull(parenttx);
txManager.rollback(parenttx);
}
}
因此,当方法testTx插入记录时,testInserted会看到它并且失败。但是日志说数据已经回滚:
00:39:09.892 [main] INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@74fbc266 testClass = TransactionTest, testInstance = TransactionTest@3c97f28a, testMethod = testTx@TransactionTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1bb4611a testClass = TransactionTest, locations = '{classpath:/core-dao-config.xml, classpath:/test-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@5f53002b]; rollback [true]
00:39:09.896 [main] DEBUG SomeDao - Running add using Connection [oracle.jdbc.driver.LogicalConnection@34311f74]
00:39:10.456 [main] DEBUG SomeDao - Running findOne
00:39:10.458 [main] DEBUG SomeDao - Running find: gkey=(-303) using Connection [oracle.jdbc.driver.LogicalConnection@34311f74]
00:39:10.752 [main] DEBUG SomeDao - <== Total: 1
00:39:10.968 [main] INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@74fbc266 testClass = TransactionTest, testInstance = TransactionTest@3c97f28a, testMethod = testTx@TransactionTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1bb4611a testClass = TransactionTest, locations = '{classpath:/core-dao-config.xml, classpath:/test-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
00:39:11.184 [main] INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@74fbc266 testClass = TransactionTest, testInstance = TransactionTest@3bd8bd66, testMethod = testInserted@TransactionTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@1bb4611a testClass = TransactionTest, locations = '{classpath:/core-dao-config.xml, classpath:/test-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@5f53002b]; rollback [true]
00:39:11.187 [main] DEBUG SomeDao - Running findOne
00:39:11.187 [main] DEBUG SomeDao - Running find: gkey=(-303)
00:39:11.402 [main] INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@74fbc266 testClass = TransactionTest, testInstance = TransactionTest@3bd8bd66, testMethod = testInserted@TransactionTest, testException = java.lang.AssertionError: expected null, but was:<DbObject{row=BaseRow{rownumStr=row#(1), status=UNCHANGED, rowscn=D, rowid=AAAkSFAAcAAAQ2uAAX, creator=TEST, created=Sun Nov 30 14:38:19 EET 2014}, gkey=-303}>, mergedContextConfiguration = [MergedContextConfiguration@1bb4611a testClass = TransactionTest, locations = '{classpath:/core-dao-config.xml, classpath:/test-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
有什么想法吗?