Spring3 / Hibernate3 / TestNG:一些测试给出了LazyInitializationException,有些则没有 [英] Spring3/Hibernate3/TestNG: some tests give LazyInitializationException, some don't

查看:119
本文介绍了Spring3 / Hibernate3 / TestNG:一些测试给出了LazyInitializationException,有些则没有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前言:我在单元测试中遇到了LazyInitializationException,我很难理解它,正如你从我的问题中看到的那样
Spring中的数据库会话 TestNG和Spring 3 LazyInitializationException,同时使用TestNG对Spring中使用的Hibernate实体类进行单元测试

The preface: I'm struggeling with LazyInitializationException in my Unit Tests, and I have a really hard time getting my head around it, as you can see from my questions Database Sessions in Spring, TestNG and Spring 3 and LazyInitializationException while unit-testing Hibernate entity classes for use in Spring, using TestNG

为了能够清楚地提出我的问题,我在GitHub上做了一个示例项目: http://github.com/niklassaers/Sample-Spring3- App / 在这个示例项目中,我重现了我在Spring3 / Hibernate3 / TestNG项目中遇到的问题。

In order to be able to ask my question clearly, I've made a sample project on GitHub: http://github.com/niklassaers/Sample-Spring3-App/ In this sample project, I reproduce the problems I'm facing in my Spring3/Hibernate3/TestNG projects.

问题:我有两个单元测试,它们非常相似,使用相同的服务为相同的项目集合测试同一个类。一个运行,一个运行失败。为什么失败的失败? (或者,为什么跑步者不会以同样的方式失败?)

The question: I have two unit tests, they are quite alike, test the same class for the same collection of items using the same service. One runs, one fails. Why does the failing one fail? (or, why doesn't the running one fail in the same way?)

这是失败的测试:

@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修复的视图。但是我已经知道在从AbstractTransactionTestNGSpringContextTests扩展的类中使用@Test注释的每个单元测试也应该包装在它自己的事务中,事实上我已经注释了两个类以在每个测试完成后回滚事务。这就是为什么我对为什么一个测试失败而一个没有失败感到困惑。任何线索或解决方案?

Below follows the console output from running my tests. I understand that I have the services wrapped in a TransactionProxyFactoryBean (see http://github.com/niklassaers/Sample-Spring3-App/blob/master/WebRoot/WEB-INF/App-Model.xml), that makes them run in a transaction, and the unit tests are not wrapped, making the test like a view. The views I've "fixed" with OpenSessionInViewInterceptor. But I have learned that each unit test annotated with @Test in a class that extends from AbstractTransactionalTestNGSpringContextTests should also be wrapped in its own transaction, and indeed I've annotated both classes to rollback the transaction after each test is finished. That's why I'm doubly puzzled as to why one test fails and one does not. Any clues or solutions?

您可以根据需要随意修改GitHub上的示例项目,所有代码都应该在那里,但我遗漏了jar-文件为了简单起见。这是承诺的完整输出:

Feel free to modify the sample project at GitHub as you see fit, all the code should be there, but I've left out the jar-files for simplicity's sake. Here's the full output as promised:

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

干杯

Nik

推荐答案

从@Test注释中删除timeOut = 1000。看起来这会导致测试在一个单独的线程中运行(很明显,堆栈跟踪会从ThreadPool中抛出异常)。事务和SessionFactory绑定到主线程,而不是测试运行程序的线程,这导致了这个异常。

Remove the timeOut=1000 from the @Test annotation. It appears that this is causing the test to be run in a separate thread (as is evident by the stacktrace, where the exception is thrown from a ThreadPool). Transactions and the SessionFactory are bound to the main thread, not to the test runner's thread, which is causing this exception.

我已经运行了你的示例代码并且已经进行了测试上班。将来,如果你在你的依赖项中包含一个Maven2 pom.xml就会很方便,这样对于那些试图编译你的代码的人来说更容易实现。

I have run your example code and have gotten the test to work. In the future, it would be handy if you included a Maven2 pom.xml with your dependencies so that it is easier for those trying to compile your code to actually do so.

这篇关于Spring3 / Hibernate3 / TestNG:一些测试给出了LazyInitializationException,有些则没有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆