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

StackOverflow https://stackoverflow.com/questions/1571017

質問

序文: 私の質問からわかるように、単体テストで LazyInitializationException に苦労しています。そして、それを理解するのに非常に苦労しています。春のデータベースセッション, TestNG と Spring 3 そして TestNG を使用して Spring で使用する Hibernate エンティティ クラスの単体テスト中に LazyInitializationException が発生する

質問をわかりやすくするために、GitHub にサンプル プロジェクトを作成しました。 http://github.com/niklassaers/Sample-Spring3-App/ このサンプル プロジェクトでは、Spring3/Hibernate3/TestNG プロジェクトで直面している問題を再現します。

質問: 2 つの単体テストがあります。それらは非常に似ており、同じサービスを使用して同じアイテムのコレクションに対して同じクラスをテストします。1 つは実行され、1 つは失敗します。なぜ失敗する人は失敗するのでしょうか?(または、実行中のものはなぜ同じように失敗しないのでしょうか?)

失敗したテストは次のとおりです。

@Test(timeOut=1000)
public void Roles() {
    User mockUser = userService.read(1);
    Assert.assertNotNull(mockUser);
    Assert.assertTrue(mockUser.isValid());
    Set<Role> roles = mockUser.getRoles();
    int size = roles.size();  // This line gives a LazyInitializationException
    Assert.assertTrue(size > 0);
}

完全なコードは ( http://github.com/niklassaers/Sample-Spring3-App/blob/master/src/tld/mydomain/sample/entities/test/FailingUserUnitTest.java )

実行テストは次のとおりです。

@Test
public void Roles() {
    for(int i = 1; i <= 4; i++) {
        User user = userService.read(i);
        Assert.assertNotNull(user);
        Assert.assertTrue(user.isValid());
        Set<Role> roles = user.getRoles();
        Assert.assertTrue(roles.size() > 0); // This line does not give a LazyInitializationException
        for(Role r : roles) {
            Assert.assertNotNull(r.getName());
            for(User someUser : r.getUsers())
                Assert.assertNotNull(someUser.getName());
        }
    }
}

完全なコードは ( http://github.com/niklassaers/Sample-Spring3-App/blob/master/src/tld/mydomain/sample/entities/test/UserUnitTest.java )

以下は、テストを実行したときのコンソール出力です。サービスが TransactionProxyFactoryBean でラップされていることを理解しています (「 http://github.com/niklassaers/Sample-Spring3-App/blob/master/WebRoot/WEB-INF/App-Model.xml)、これにより、それらはトランザクション内で実行され、単体テストはラップされず、テストがビューのようになります。OpenSessionInViewInterceptor で「修正」したビュー。しかし、AbstractTransactionalTestNGSpringContextTests から拡張されたクラス内の @Test でアノテーションが付けられた各単体テストも独自のトランザクションでラップする必要があることを学び、実際、各テストの終了後にトランザクションをロールバックするように両方のクラスにアノテーションを付けました。だからこそ、なぜ一方のテストが失敗し、もう一方のテストが失敗するのか、私は二重に困惑しています。手がかりや解決策はありますか?

GitHub のサンプル プロジェクトを必要に応じて自由に変更してください。すべてのコードがそこにあるはずですが、わかりやすくするために jar ファイルは省略しています。約束どおりの完全な出力は次のとおりです。

[Parser] Running:
  /Users/niklas/Documents/Eclipse/SampleProject/testng.xml

2009-10-15 10:16:16,066 [TestNGInvoker-Roles()] ERROR org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: tld.mydomain.sample.entities.User.roles, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: tld.mydomain.sample.entities.User.roles, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentSet.size(PersistentSet.java:162)
    at tld.mydomain.sample.entities.test.FailingUserUnitTest.Roles(FailingUserUnitTest.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:607)
    at org.testng.internal.InvokeMethodRunnable.runOne(InvokeMethodRunnable.java:49)
    at org.testng.internal.InvokeMethodRunnable.run(InvokeMethodRunnable.java:40)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:637)

===============================================
SampleAppSuite
Total tests run: 3, Failures: 1, Skips: 0
===============================================

乾杯

ニック

役に立ちましたか?

解決

@Test アノテーションから timeOut=1000 を削除します。これにより、テストが別のスレッドで実行されるようです (スタックトレースで明らかなように、ThreadPool から例外がスローされます)。トランザクションと SessionFactory はテスト ランナーのスレッドではなくメイン スレッドにバインドされているため、この例外が発生します。

サンプルコードを実行し、テストが機能するようになりました。将来的には、コードをコンパイルしようとする人が実際にコンパイルしやすくなるように、依存関係に Maven2 pom.xml を含めると便利です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top