Java 使用TestNG和Spring事务进行并发测试

Java 使用TestNG和Spring事务进行并发测试,java,spring,testng,spring-transactions,spring-test,Java,Spring,Testng,Spring Transactions,Spring Test,我有一个服务类,该服务类用@Transactionalpropagation=Propagation.REQUIRES\u NEW注释,其公共方法在接口中定义: public interface UniqueKeyGeneratorService { void initializeUniqueKeys(Entity entity); } @Transactional(propagation = Propagation.REQUIRES_NEW) public final class K

我有一个服务类,该服务类用@Transactionalpropagation=Propagation.REQUIRES\u NEW注释,其公共方法在接口中定义:

public interface UniqueKeyGeneratorService {
    void initializeUniqueKeys(Entity entity);
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public final class KeyGeneratorServiceImpl implements UniqueKeyGeneratorService, DisposableBean {

    private final UniqueKeyGeneratorStrategy strategy;

    private KeyGeneratorServiceImpl(final UniqueKeyGeneratorStrategy strategy) {
        this.strategy = strategy;
    }

    @Override
    public void initializeUniqueKeys(final Entity entity) {
        // ... the business logic
    }

    // ... some private methods

    @Override
    public void destroy() {
        strategy.destroy();
    }
}
bean是使用FactoryBean来初始化策略的

我想测试服务,所以我配置了一个嵌入式H2数据库,使用Apache Commons DBCP定义了一个连接池,并编写了适当的测试代码,如下所示:

@ContextConfiguration("/path/to/xml/config/file.xml")
@Transactional
public class TestUniqueKeyGeneratorService extends AbstractTransactionalTestNGSpringContextTests {

    @Autowired
    private UniqueKeyGeneratorService service;

    @Test
    @Rollback(false)
    public void testCodeGeneration() {
        final Department department1 = new Department();
        department1.setName("Abcd");
        service.initializeUniqueKeys(department1);
        final String code = department1.getCode();

        Assert.assertNotNull(code);
    }

    // ... some more test methods
}
而且

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.h2.Driver"/>
    <property name="url" value="jdbc:h2:mem:db1"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  </bean>

  <tx:annotation-driven/>

  <bean id="uniqueKeyGeneratorService"
    class="com.mycompany.uniquekey.UniqueKeyGeneratorServiceFactoryBean">
    <property name="dataSource" ref="dataSource"/>
  </bean>

</beans>
你知道如何处理这个异常吗


p、 我审阅了H2文档,它支持嵌入式模式下的多个连接

答案位于

我在另一个线程中找到了答案:[TestNG multi-threaded test with Spring@Transactional][1][1]:Mmm,在测试中放入@TestinvocationCount=10,singleThreaded=false,threadPoolSize=3。我不确定注释是否足够。但我自己无法测试它,我想知道它。你能吗?不,没有什么不同。
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connection is closed.
    at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:240) ~[org.springframework.jdbc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) ~[org.springframework.transaction-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.startTransaction(TransactionalTestExecutionListener.java:514) ~[org.springframework.test-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.startNewTransaction(TransactionalTestExecutionListener.java:272) ~[org.springframework.test-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:165) ~[org.springframework.test-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:358) ~[org.springframework.test-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextBeforeTestMethod(AbstractTestNGSpringContextTests.java:146) [org.springframework.test-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_31]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_31]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_31]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_31]
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:653) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111) [org.testng-6.8.jar:6.8-201210030754]
    at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64) [org.testng-6.8.jar:6.8-201210030754]
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) [na:1.6.0_31]
    at java.util.concurrent.FutureTask.run(FutureTask.java:138) [na:1.6.0_31]
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [na:1.6.0_31]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [na:1.6.0_31]
    at java.lang.Thread.run(Thread.java:662) [na:1.6.0_31]
Caused by: java.sql.SQLException: Connection is closed.
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen(PoolingDataSource.java:185) ~[org.apache.commons-dbcp-1.4.jar:1.4]
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.getAutoCommit(PoolingDataSource.java:234) ~[org.apache.commons-dbcp-1.4.jar:1.4]
    at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:218) ~[org.springframework.jdbc-3.1.3.RELEASE.jar:3.1.3.RELEASE]
    ... 24 common frames omitted