LazyInitializationException,同时使用TestNG对Spring中使用的Hibernate实体类进行unit testing

在我的Spring配置中,我已经要求会话在我的视图中保持打开状态:

    

但是,这个bean似乎并不认为我的TestNGunit testing是一种观点。 ;-)那没关系,但是unit testing是否有类似的bean,以便在unit testing时避免可怕的LazyInitializationException? 到目前为止,我的一半unit testing因此而死亡。

我的unit testing通常如下所示:

 @ContextConfiguration({"/applicationContext.xml", "/applicationContext-test.xml"}) public class EntityUnitTest extends AbstractTransactionalTestNGSpringContextTests { @BeforeClass protected void setUp() throws Exception { mockEntity = myEntityService.read(1); } /* tests */ @Test public void LazyOneToManySet() { Set entities = mockEntity.getSomeEntitySet(); Assert.assertTrue(entities.size() > 0); // This generates a LazyInitializationException } } 

我已经尝试将setUp()更改为:

 private SessionFactory sessionFactory = null; @BeforeClass protected void setUp() throws Exception { sessionFactory = (SessionFactory) this.applicationContext.getBean("sessionFactory"); Session s = sessionFactory.openSession(); TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s)); mockEntity = myEntityService.read(1); } 

但是我认为这是错误的做法,我把交易搞砸了以后的测试。 有没有类似OpenSessionInTestInterceptor的东西,有没有更好的方法来做到这一点,或者这是做到这一点的方式,在这种情况下我有什么误解?

干杯

嗯..这里不是一个聪明的屁股,但这不是setUp()用途。

基本思想是让您的测试具有自给自足性和可重入性,这意味着您不应该依赖具有特定记录的数据库,也不应该永久地更改测试中的数据库。 因此,这个过程是:

  1. setUp()创建任何必要的记录
  2. 运行您的实际测试
  3. tearDown()清理(​​如果需要tearDown()

(1),每个(2)和(3)都在单独的事务中运行 – 因此你得到LazyInitializationException的问题。 移动mockEntity = myEntityService.read(1); 从setUp到你的实际测试,它会消失; 如果您需要创建一些测试数据,请使用setUp,而不是作为单个测试的直接补充。

我使用JUnit进行测试,因此您需要将以下示例调整为TestNG。 Personnaly我使用SpringJUnit4ClassRunner来绑定基础测试类中的事务:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/applicationContext-struts.xml") @TransactionConfiguration(transactionManager = "transactionManager") @Transactional public abstract class BaseTests { 

在“@Before”中,我在RequestContextHolder中注入一个MockHttpServletRequest:

 @Before public void prepareTestInstance() throws Exception { applicationContext.getBeanFactory().registerScope("session", new SessionScope()); applicationContext.getBeanFactory().registerScope("request", new RequestScope()); MockHttpServletRequest request = new MockHttpServletRequest(); ServletRequestAttributes attributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attributes); ....... 

我从手册中获取了信息