Pergunta

O prefácio: Estou me esforçando com a LazyinitializationException em meus testes de unidade e tenho muita dificuldade em entender, como você pode ver nas minhas perguntasSessões de banco de dados na primavera, Testng e primavera 3 e LazyinitializationException enquanto testam as classes de entidade de hibernato para uso na primavera, usando o testng

Para poder fazer minha pergunta com clareza, fiz um exemplo de projeto no Github: http://github.com/niklassaers/sample-spring3-app/ Neste projeto de amostra, reproduzo os problemas que estou enfrentando nos meus projetos Spring3/Hibernate3/Testng.

A questão: Eu tenho dois testes de unidade, eles são iguais, testam a mesma classe para obter a mesma coleção de itens usando o mesmo serviço. Um corre, um falha. Por que a falha falha? (Ou, por que a corrida não falha da mesma maneira?)

Aqui está o teste de falha:

@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);
}

código completo em ( http://github.com/niklassaers/sample-spring3-app/blob/master/src/tld/mydomain/sample/entities/test/failinguserunittest.java )

E aqui está o teste em execução:

@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());
        }
    }
}

código completo em ( http://github.com/niklassaers/sample-spring3-app/blob/master/src/tld/mydomain/sample/entities/test/userunittest.java )

Abaixo segue a saída do console da execução dos meus testes. Entendo que tenho os serviços envolvidos em um transactionProxyFactoryBean (ver http://github.com/niklassaers/sample-spring3-app/blob/master/webroot/web-inf/app-model.xml), isso os faz funcionar em uma transação e os testes de unidade não são embrulhados, tornando o teste como uma exibição. As visualizações que corrigi "com o OpenSessionInViewIntercept. Mas aprendi que cada teste de unidade anotou com o @Test em uma classe que se estende do abstranTransactionAltestngspringContextTests também deve ser envolvida em sua própria transação e, de fato, anotei as duas classes para reverter a transação após o término de cada teste. É por isso que estou duplamente intrigado com o motivo pelo qual um teste falha e um não. Alguma pista ou soluções?

Sinta-se à vontade para modificar o projeto de amostra no Github, como você achar melhor, todo o código deve estar lá, mas deixei de fora os arquivos de jarra por uma questão de simplicidade. Aqui está a saída completa, conforme prometido:

[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
===============================================

Felicidades

Nik

Foi útil?

Solução

Remova o tempo limite = 1000 da anotação @Test. Parece que isso está fazendo com que o teste seja executado em um encadeamento separado (como é evidente pelo Stacktrace, onde a exceção é lançada de um threadpool). As transações e o SessionFactory estão vinculadas ao encadeamento principal, não ao thread do corredor de teste, que está causando essa exceção.

Eu executei seu código de exemplo e fiz o teste funcionar. No futuro, seria útil se você incluísse um maven2 pom.xml com suas dependências, para que seja mais fácil para quem tenta compilar seu código para realmente fazê -lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top