一個Struts2.0+hibernate3.2+Spring2.5+oracle10g的項目。實現完DAO層后,想對Dao層做下測試。以前都是用的Junit3.8,這次換了最新的Junit4.4,但是在寫測試類時遇到不少麻煩,將碰到的問題和解決方法記錄下來,供后來的朋友們參考。
下面分別講解在Junit4.4和Junit3.8下如何寫測試類。
對於Junit3.8:
Spring的DAO層的測試,spring-test.jar包里有個AbstractTransactionalDataSourceSpringContextTests類,只要繼承它,然后重寫getConfigLocations方法就可以了。比較簡單,而且又支持回滾,沒有數據庫的耗時操作。
對於你所有的applicationContext.xml等spring配置文件,你都不用動。Eclipse默認的classpath路徑是項目路徑下的build/classes,注意不要被你的ant寫的build覆蓋了,而ant的build又沒有編譯test包。最終找不到測試類。
下面先寫一個基本的測試類,其他的只要繼承這個類並添加test方法即可。
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
public class BaseDaoTestCaseJunit3 extends
AbstractTransactionalDataSourceSpringContextTests {
protected final static Log log = LogFactory.getLog(BaseDaoTestCaseJunit3.class);
@Override
protected String[] getConfigLocations(){
this.setAutowireMode(AUTOWIRE_BY_NAME);
return new String[]{"classpath:/applicationContext.xml","classpath:/spring-config-*.xml"};
}
public void testConfig() {
assertNotNull("spring-mock context has bean init()",this.applicationContext);
}
}
下面這個類繼承自上面的BaseDaoTestCaseJunit3,只是測試了下CustInfoDao里面的findByEmail方法。
import com.psi.domain.CustInfo;
public class CustInfoDaoTests3 extends BaseDaoTestCaseJunit3 {
private CustInfoDao ciDao;
private CustInfo ci;
public CustInfoDaoTests3(){}
public void setCustInfoDao(CustInfoDao ciDao){
this.ciDao = ciDao;
}
public void getList(){
try{
ci = ciDao.findByEmail("sue76543@ms5.url.com.tw"); //此方法直接返回對象.
assertNotNull(ci.getId());
}catch(Exception e){
e.printStackTrace();
}
}
}
下面講講Junit4.4的寫法:
Junit4用了完全不同於Junit3的寫法,它的配置文件等都只需要在annotation里標注即可。TransactionManager是你在application里配置的TransactionManager。
package com.psi.dao;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/applicationContext.xml","classpath:/spring-config-*.xml"})
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
@Transactional
public class BaseDAOTestCaseJunit44 {
//本類作為基類,所有要用到的東西都在annotation里配置了。所以什么內容都不用寫了。
}
//Dao測試類繼承自上面的基類,並添加了個測試方法findByEmail。
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.psi.domain.CustInfo;
public class CustInfoDaoTests extends BaseDAOTestCaseJunit44 {
private CustInfoDao ciDao;
private CustInfo ci;
public CustInfoDaoTests(){}
@Autowired
public void setCustInfoDao(CustInfoDao ciDao){
this.ciDao = ciDao;
}
@Before
public void init(){}
@Test
public void getList(){
try{
ci = ciDao.findByEmail("sue76543@ms5.url.com.tw");
assertNotNull(ci.getId());
}catch(Exception e){
e.printStackTrace();
}
}
}
就這么簡單,但是要注意要加載相應的包,Spring-test.jar, apache的commons-下的包最好都加上。(項目中你基本都能用上)
還要注意你的配置文件路徑。
我還碰到過下面這個錯誤:
Caused by: java.lang.NullPointerException
at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:374)
at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:374)
這是Eclipse的Bug,它在測試環境下不能自動加載到SystemLibrary下的所有包,所以你需要將你的Library改成user-library即可。