PDA

View Full Version : Unit tests and LazyInitializationException


camach
Aug 14th, 2004, 06:37 PM
I'm using Hibernate & Spring and I'm looking for some best practices for writing unit tests. I'm currently getting a LazyInitializationException when executing this unit test:

public void testUserInRoleOk() throws Exception {

WebUser user = this.userService.retrieveWebUser("johndoe@yahoo.com", "password");
assertTrue(this.userService.isUserInRole(user, WebRoleEnum.CUSTOMER));
}

The first line executes ok but then the exception is thrown in the implementation of "isUserInRole".

The WebUser object has a Hibernate relationship with WebRole, there's a WebUser.getWebRoles method that returns a Set of WebRoles and that is exactly what the "isUserInRole" method is doing (and then getting the exception).

I'm using a HibernateTransactionManager and TransactionInterceptor for both methods on the service:"retrieveWebUser" and "isUserInRole".

Now when I deploy this on a web app I guess I would use the OpenSessionInViewInterceptor but what about for unit tests? Is there an elegant way to have a Session stay open for the duration of the test method? I have a feeling I may be missing something.

Thanks
Andres

irbouho
Aug 14th, 2004, 06:56 PM
You need to simulate the OpenSessionInViewInterceptor behaviour in your Unit Tests.
I use the following class for Spring/Hibernate/JUnit tests


//Hibernate imports
import net.sf.hibernate.FlushMode;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;

//Spring imports
import org.springframework.orm.hibernate.SessionFactoryUt ils;
import org.springframework.orm.hibernate.SessionHolder;
import org.springframework.transaction.support.Transactio nSynchronizationManager;

//Taha imports
import org.taha.spring.BaseSpringTest;

/**
* @author <a href="mailto:irbouh@videotron.ca">Omar Irbouh</a>
* @version 0.1
* @since 2004.03.03
*/
public abstract class BaseSpringHibernateTest extends BaseSpringTest {

protected static final String SESSION_FACTORY = "sessionFactory";

protected SessionFactory sessionFactory = null;

protected void setUp() throws Exception {
super.setUp();
sessionFactory = (SessionFactory) getApplicationContext().getBean(SESSION_FACTORY);
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
session.setFlushMode(FlushMode.NEVER);
TransactionSynchronizationManager.bindResource(ses sionFactory, new SessionHolder(session));
}

protected void tearDown() throws Exception {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(s essionFactory);
SessionFactoryUtils.closeSessionIfNecessary(sessio nHolder.getSession(), sessionFactory);
super.tearDown();
}
}


org.taha.spring.BaseSpringTest is a simillar abstract class responsible for building the ApplicatinContext. You can remove the dependance on BaseSpringTest and add a method getApplicationContext() that returns the ApplicationContext.

HTH.

camach
Aug 14th, 2004, 07:06 PM
Thanks! I also found a reference on the Hibernate boards:

http://forum.hibernate.org/viewtopic.php?t=929167

The example posted there does not have the line:

session.setFlushMode(FlushMode.NEVER);

Just curious on your thoughts on how FlushMode affects things.

irbouho
Aug 14th, 2004, 07:24 PM
Good point!!!

I use BaseSpringHibernateTest mainly in readonly + lazy initialization scenarios. I added this line to enforce no updates can be executed in the underlying code.

Now that Jüergen added checkWriteOperationAllowed in HibernateTemplate, I no longer need to keep this line, and the class may serve for readonly/readwrite tests. So, please remove it if you want to use the class in your tests.