为什么在junit期间在AbstractDAO中注入SessionDA时,SessionFactory为null?

时间:2012-08-28 10:05:15

标签: hibernate junit4

我有单元测试来测试hibernate过程让我通过这个

以下是我的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;
    }
}

这是我的concreteDAO,它扩展了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;
    }

...
}

这是我的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()));
}

SessionFactory在BaseDAO中被正确注入,但是当它出现时 Session session = sessionFactory.openSession();中的LoginDAO,它变为空!

怎么会发生这种情况?需要一些解释,如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

使用真实对象进行测试确实是一种不好的做法,除非这些测试是集成测试。您有用于此目的的模拟对象:jmockEasyMockMockito是您将要搜索的最佳Java库。

也许您可以尝试使用类似OpenSessionInView的内容查找您的JPA或Hibernate Session,以查看MVC模式的View部分。它可能是这样的:

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

或者做这样的事情:

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