LazyInitializationException mentre l'unità di prova di classi entità Hibernate per l'uso in primavera, utilizzando TestNG

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

Domanda

Nella mia configurazione Primavera, ho chiesto che la sessione dovrebbe rimanere aperta in mio punto di vista:

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

Tuttavia, questo fagiolo obiously non considera mio test di unità TestNG come una visione. ;-) Va tutto bene, ma c'è un fagiolo simile per i test di unità in modo che evito il LazyInitializationException temuto mentre unit test? Finora, la metà dei miei test di unità muoiono a causa di esso.

Il mio test di unità si presenta tipicamente come questo:

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



}

Ho provato a cambiare il setup () a questo:

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

ma credo che questo è il modo sbagliato per andare a questo proposito, e mi rovinare la transazione per le prove successive. C'è qualcosa come un OpenSessionInTestInterceptor, ci sono modi migliori di fare questo, o è questo il modo di farlo e in quel caso che cosa ho capito male su di esso?

Saluti

Nik

È stato utile?

Soluzione

Umm .. non essere una smart-ass qui, ma non è quello che è stato destinato per setUp().

L'idea di base è quella di avere i test essere autosufficienti e rientrante nel senso che non dovrebbe dipendere dal database di avere record particolari, né si dovrebbe modificare in modo permanente il database nel tuo test. Il processo, quindi, è quello di:

  1. Crea tutti i record necessari setUp()
  2. Esegui i test reali
  3. Clean up (se necessario) in tearDown()

(1), ciascuna (2), e (3) tutti corrono in transazioni separate - da qui il problema che stai ricevendo con LazyInitializationException. Spostare mockEntity = myEntityService.read(1); dal setUp nella vostra prova effettiva (s) e andrà via; utilizzare Impostazione se avete bisogno di creare alcuni dati di test, non come supplemento diretto al tuo singolo test.

Altri suggerimenti

I utilizza JUnit per i miei test, quindi è necessario per adattare il seguente esempio per TestNG. Personnaly Io uso SpringJUnit4ClassRunner di legare le transazioni in una classe di test di base:

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

E in "@Before", ho iniettare un MockHttpServletRequest nella 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);

     .......

Ho preso le informazioni dal manuale rel="noreferrer">

scroll top