Spring3/Гибернация3/TestNG:некоторые тесты выдают исключение LazyInitializationException, некоторые нет

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

Вопрос

Предисловие: Я борюсь с LazyInitializationException в своих модульных тестах, и мне действительно трудно разобраться в этом, как вы можете видеть из моих вопросов Сеансы базы данных весной, Тестовый стержень и пружина 3 и Исключение LazyInitializationException во время модульного тестирования Hibernate entity classes для использования в Spring с использованием TestNG

Чтобы иметь возможность четко задать свой вопрос, я создал пример проекта на GitHub: http://github.com/niklassaers/Sample-Spring3-App/ В этом примере проекта я воспроизводю проблемы, с которыми сталкиваюсь в своих проектах Spring3 / Hibernate3 / TestNG.

Этот вопрос: У меня есть два модульных теста, они очень похожи, тестируют один и тот же класс для одной и той же коллекции элементов, используя один и тот же сервис.Один бежит, другой терпит неудачу.Почему тот, кто терпит неудачу, терпит неудачу?(или, почему запущенный не выходит из строя таким же образом?)

Вот неудачный тест:

@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.Но я узнал, что каждый модульный тест, аннотированный с помощью @Test в классе, который расширяется от AbstractTransactionalTestNGSpringContextTests, также должен быть обернут в свою собственную транзакцию, и действительно, я аннотировал оба класса для отката транзакции после завершения каждого теста.Вот почему я вдвойне озадачен тем, почему один тест проваливается, а другой нет.Есть какие-нибудь подсказки или решения?

Не стесняйтесь изменять пример проекта на 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
===============================================

Ваше здоровье

Ник

Это было полезно?

Решение

Удалите значение timeOut=1000 из аннотации @Test.Похоже, что это приводит к запуску теста в отдельном потоке (как видно из stacktrace, где исключение генерируется из ThreadPool).Транзакции и SessionFactory привязаны к основному потоку, а не к потоку тестировщика, который вызывает это исключение.

Я запустил ваш пример кода и добился того, что тест заработал.В будущем было бы удобно, если бы вы включили Maven2 pom.xml в свои зависимости, чтобы тем, кто пытается скомпилировать ваш код, было проще это сделать на самом деле.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top