LazyinitializationException enquanto testam as classes de entidade de hibernato para uso na primavera, usando o testng
-
20-09-2019 - |
Pergunta
Na minha configuração de primavera, pedi que a sessão permanecesse aberta em meus pontos de vista:
<bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="flushMode" value="0" />
</bean>
No entanto, esse feijão obruecamente não considera meus testes de unidade de teste como uma visualização. ;-) Está tudo bem, mas existe um feijão semelhante para testes de unidade para que eu evite a temida LazyinitializationException enquanto testava unidade? Até agora, metade dos meus testes de unidade morrem por causa disso.
Meu teste de unidade normalmente se parece com o seguinte:
@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
}
}
Eu tentei alterar a configuração () para isso:
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);
}
Mas acredito que essa é a maneira errada de fazer isso, e eu mexendo na transação para testes posteriores. Existe algo como um OpenSessionIntestInterceptor, existem maneiras melhores de fazer isso, ou é a maneira de fazê -lo e, nesse caso, o que eu entendi mal sobre isso?
Felicidades
Nik
Solução
Umm .. para não ser um assassino inteligente aqui, mas não é isso setUp()
foi destinado a.
A idéia básica é fazer com que seus testes sejam auto-suficientes e reentrantes, o significado que você não deve depender do banco de dados com registros específicos nem deve alterar permanentemente o banco de dados em seu teste. O processo, portanto, é::
- Criar os registros necessários em
setUp()
- Execute seus testes reais
- Limpe (se necessário) em
tearDown()
(1), cada um (2) e (3) todos executam em transações separadas - daí o problema que você está recebendo com a LazyinitializationException. Jogada mockEntity = myEntityService.read(1);
da configuração para os seus testes reais e ele desaparecerá; Use a configuração se precisar criar alguns dados de teste, não como suplemento direto para o seu teste individual.
Outras dicas
Eu uso o JUNIT para meus testes, então você precisa adaptar o exemplo a seguir para testar. Personnaly eu uso o springjunit4classrunner para vincular transações em uma classe de teste base:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-struts.xml")
@TransactionConfiguration(transactionManager = "transactionManager")
@Transactional
public abstract class BaseTests {
E em "@Before", injeto um MockHttPervletRequest no 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);
.......
Eu peguei as informações do manual