序文:ユニットテストでLazyInitializationExceptionに苦労していますが、私の質問からわかるように 、Spring 、TestNG、Spring 3のデータベースセッションと、Hibernateのユニットテスト中のLazyInitializationExceptionに頭を悩ませています。 TestNGを使用してSpringで使用するエンティティクラス
明確に質問できるように、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);
}
実行中のテストは次のとおりです。
@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());
}
}
}
以下は、私のテストを実行したときのコンソール出力です。TransactionProxyFactoryBean( http://github.com/niklassaers/Sample-Spring3-App/blob/master/WebRoot/WEB-INF/App-Model.xmlを参照)でラップされたサービスを実行できることを理解していますトランザクションで、単体テストはラップされないため、テストはビューのようになります。OpenSessionInViewInterceptorで「修正」したビュー。しかし、AbstractTransactionalTestNGSpringContextTestsから拡張されたクラスで@Testで注釈が付けられた各単体テストも、独自のトランザクションでラップする必要があることを学びました。実際、各テストの終了後にトランザクションをロールバックするように両方のクラスに注釈を付けました。そのため、1つのテストが失敗し、もう1つが失敗する理由について私は二重に戸惑っています。手がかりや解決策はありますか?
必要に応じて、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
===============================================
乾杯
ニック