¿Por qué SessionFactory es nulo en concreteDAO cuando se inyectó en AbstractDAO durante junit?

I have unit test to test hibernate process let me go through this

Below is my AbstractDAO

public abstract class BaseDAO {

    protected JdbcTemplate jdbcTemplate;
    protected SessionFactory sessionFactory;
    protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    ...

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}

Here is my concreteDAO where it extends BaseDAO

public class LoginDAO extends BaseDAO implements InitializingBean {

    private static final Logger log = Logger.getLogger(LoginDAO.class);
    private MD5PasswordEncoder passwordEncoder;
    private SaltSource saltSource;

    public User getLoggedinUserByUserid(Long userid){
        log.info("in getLoggedinUserByUserid"); 
        User result = null;
        Session session = sessionFactory.openSession();

        try {
            session.beginTransaction();

            result = (User) session.get(User.class, userid);

            session.getTransaction().rollback();
            session.close();

        } catch (Exception e) {
            log.error(e,e);

            session.getTransaction().rollback();
            session.close();
        }

        return result;
    }

...
}

here is my junit

@Test
public void shouldReturnCorrectlyUserWhenCallingGetLoggedinUserByUseridMethod() {

    // Given When
    User adminUser = loginDAO.getLoggedinUserByUserid(1l);

    // Then
    assertNotNull(adminUser);
    assertEquals("sadmin", adminUser.getUsername());
    assertEquals("ecedee8662a0bcd15c157e5734056ac5", adminUser.getPassword());
    assertEquals(1, adminUser.getStatus());
    assertEquals("TS", adminUser.getFirstname());
    assertEquals("Sys Admin Person", adminUser.getLastname());
    assertEquals(0, adminUser.getIdType());
    assertTrue(adminUser.getEnabled());
    assertTrue(adminUser.getAuthenLocal());
    assertTrue(StringUtils.isBlank(adminUser.getTitle()));
}

the SessionFactory was injected alright in the BaseDAO,but when it came to Session session = sessionFactory.openSession(); in LoginDAO, it became null!

How could this happen? need some explanation and How do I fix this problem?

preguntado el 28 de agosto de 12 a las 11:08

1 Respuestas

It is really a bad practise to test with real objects, unless these tests are integration tests. You have mock objects for that purpose: jmock, EasyMock, Mockito are the best java libraries you will find if you will search for.

Maybe you could try to lookup your JPA or Hibernate Session with something like OpenSessionInView do it for the View part of MVC pattern. It could be something like that:

public abstract class AppContextTestCase extends TestCase {

    protected FileSystemXmlApplicationContext context = null;
    protected SessionFactory sessionFactory = null;

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        String[] contextLocations = new String[2];
        contextLocations[0] = "web/WEB-INF/applicationContext.xml";
        contextLocations[1] = "test/dataSource-local.xml";
        context = new FileSystemXmlApplicationContext(contextLocations);
        sessionFactory = (SessionFactory) context.getBean("sessionFactory");
        Session session = SessionFactoryUtils.getSession(sessionFactory, true);
        TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
    }

    /* (non-Javadoc)
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
        SessionFactoryUtils.closeSessionIfNecessary(sessionHolder.getSession(), sessionFactory);
        context = null;
        super.tearDown();
    }
}

Or doing something like this:

protected void setUp() throws Exception {    
    Session session = SessionFactoryUtils.getSession(sessionFactory, true);
    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}

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

Respondido 28 ago 12, 12:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.