1

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

  <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    <property name="sessionFactory" ref="sessionFactory"/>
    <property name="flushMode" value="0" />
  </bean> 

然而,这个 bean 显然没有将我的 TestNG 单元测试视为一个视图。;-) 没关系,但是是否有用于单元测试的类似 bean,以便我在单元测试时避免可怕的 LazyInitializationException?到目前为止,我有一半的单元测试因此而死。

我的单元测试通常如下所示:

@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<SomeEntity> 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 这样的东西,有没有更好的方法来做到这一点,或者这是这样做的方式,在这种情况下我误解了什么?

干杯

尼克

4

2 回答 2

6

我使用 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);

     .......

我从手册中获取信息

于 2009-10-09T13:18:57.200 回答
1

嗯..不要在这里成为一个聪明人,但这不是我们setUp()的本意。

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

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

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

于 2009-10-09T18:32:11.287 回答