3

私は TestNG を使用して、基本クラスとして AbstractTransactionalTestNGSpringContextTests を使用して永続化 Spring モジュール (JPA + Hibernate) をテストしています。すべての重要な部分 @Autowired、@TransactionConfiguration、@Transactional は問題なく動作します。

問題は、threadPoolSize=x、invocationCount=y TestNG アノテーションを使用して並列スレッドでテストを実行しようとすると発生します。

WARNING: Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@174202a] 
to process 'before' execution of test method [testCreate()] for test instance [DaoTest] java.lang.IllegalStateException:
Cannot start new transaction without ending existing transaction: Invoke endTransaction() before startNewTransaction().
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:123)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:374)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextBeforeTestMethod(AbstractTestNGSpringContextTests.java:146)

...この問題に直面した人はいますか?

コードは次のとおりです。

@TransactionConfiguration(defaultRollback = false)
@ContextConfiguration(locations = { "/META-INF/app.xml" })
public class DaoTest extends AbstractTransactionalTestNGSpringContextTests {

@Autowired
private DaoMgr dm;

@Test(threadPoolSize=5, invocationCount=10)
public void testCreate() {
    ...
    dao.persist(o);
    ...
}
...

更新: AbstractTransactionalTestNGSpringContextTests は、他のすべてのテスト スレッドが独自のトランザクション インスタンスを取得しない場合に、メイン スレッドに対してのみトランザクションを維持しているようです。これを解決する唯一の方法は、AbstractTestNGSpringContextTests を拡張し、各メソッドごとに (@Transactional アノテーションの代わりに) プログラムで (つまり、TransactionTemplate を使用して) トランザクションを維持することです。

@Test(threadPoolSize=5, invocationCount=10)
public void testMethod() {
    new TransactionTemplate(txManager).execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            // transactional test logic goes here
        }
    }
}
4

2 に答える 2

2

トランザクションは同じスレッドで開始する必要があります。詳細は次のとおりです。

Spring3/Hibernate3/TestNG: 一部のテストでは LazyInitializationException が発生し、一部のテストでは発生しません

于 2010-02-05T04:10:08.727 に答える
2

これは、むしろ org.springframework.test.context.TestContextManager がスレッドセーフではないことに起因すると思いませんか ( https://jira.springsource.org/browse/SPR-5863を参照)。

Transactional TestNG テストを並行して起動したいときに同じ問題に直面しました。Spring が実際にトランザクションを正しいスレッドにバインドしようとしていることがわかります。

ただし、これはこの種のエラーでランダムに失敗します。AbstractTransactionalTestNGSpringContextTests を次のように拡張しました。

@Override
@BeforeMethod(alwaysRun = true)
protected synchronized void springTestContextBeforeTestMethod(
        Method testMethod) throws Exception {
    super.springTestContextBeforeTestMethod(testMethod);
}

@Override
@AfterMethod(alwaysRun = true)
protected synchronized void springTestContextAfterTestMethod(
        Method testMethod) throws Exception {
    super.springTestContextAfterTestMethod(testMethod);
}

(キーは同期されています...)

そして今では魅力のように機能しています。ただし、Spring 3.2 が完全に並列化されるのが待ちきれません!

于 2012-01-05T11:07:03.970 に答える