LazyInitializationException mientras que la unidad de pruebas de las clases de entidad de Hibernate para su uso en la primavera, utilizando TestNG

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

Pregunta

En la configuración de mi primavera, le he pedido que la sesión debe permanecer abierta en mis puntos de vista:

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

Sin embargo, este bean Obviamente, tenemos no tiene en cuenta mis pruebas unitarias TestNG como una vista. ;-) Eso está bien, pero no es un grano similar para las pruebas unitarias para que evito la LazyInitializationException temida mientras que la unidad de pruebas? Hasta el momento, la mitad de mis pruebas de unidad mueren a causa de ella.

Mi prueba de la unidad normalmente se ve así:

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



}

He intentado cambiar la Configuración () a esto:

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

pero creo que esta es la manera equivocada de hacerlo, y me lío la transacción para pruebas posteriores. ¿Hay algo así como un OpenSessionInTestInterceptor, ¿Hay mejores maneras de hacer esto, o esto es la manera de hacerlo y en ese caso lo he entendido mal al respecto?

Saludos

Nik

¿Fue útil?

Solución

Umm .. no ser un smart-culo aquí, pero eso no es lo que estaba destinado a setUp().

La idea básica es que sus pruebas sean autosuficientes y re-entrante lo que significa que no debe depender de bases de datos con registros particulares ni debe alterar permanentemente la base de datos en su prueba. El proceso, por lo tanto, es a:

  1. Crear todos los registros necesarios en setUp()
  2. ejecutar las pruebas reales
  3. Limpiar (si es necesario) en tearDown()

(1), cada uno (2) y (3) todos corren en transacciones separadas - por lo tanto el problema que está recibiendo con LazyInitializationException. mockEntity = myEntityService.read(1); moverse desde la configuración en su prueba (s) real y que va a desaparecer; utilizar configuración si es necesario crear algunos datos de prueba, no como suplemento directo a su prueba individual.

Otros consejos

I utiliza JUnit para mis pruebas, por lo que necesita para adaptar el siguiente ejemplo para TestNG. Personnaly utilizo SpringJUnit4ClassRunner de obligar a las transacciones en una clase de prueba de base:

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

Y en "@Before", me inyecto una MockHttpServletRequest en el RequestContextHolder:

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

     .......

Tomé la información del manual de rel="noreferrer">

scroll top