磨蹭了很久,终于开始用UnitTest。原因一是和大家一样,不想晚上做噩梦,二是在Spring下对业务层TDD,能够不需要Tomcat,完全摆脱对显示层开发进度的依赖,而专注快速的开发业务层。
但是我们也只在业务层使用UnitTest,因为显示层至今没有什么好的UnitTest方法,而我们的业务逻辑又严格封装在业务层,Controler层只做个组装分派的基本动作,没必要花大力气去测试。
在Spring下的测试很简单,在Spring-mock.jar里有一个AbstractDependencyInjectionSpringContextTests,负责ApplicationContext的载入和属性的动态注入。(详看该类的JavaDoc) 所以,只要再写一个测试父类Extend它,用DbUnit负责测试前后的数据备份和恢复。子类就可以非常轻松,只需指定特定的Context文件路径, 通过成员变量配置以下数据备份和载入的策略,还有把需要注入的成员变量设为protected就可以了. 父类的源代码: package com.itorgan.xxxx;
import org.dbunit.database.DatabaseConnection; import org.dbunit.database.DatabaseSequenceFilter; import org.dbunit.dataset.xml.XmlDataSet; import org.dbunit.dataset.FilteredDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.filter.ITableFilter; import org.dbunit.operation.DatabaseOperation; import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.itorgan.util.DbUtil;
import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.File; import java.util.ArrayList;
public class DAOTestCase extends AbstractDependencyInjectionSpringContextTests {
protected ArrayList<String> contexts = null;
//DBUnit相关属性 protected DatabaseConnection dbunitConn = null;
/** * 是否需要测试前备份 */ protected boolean needBackup = false; /** * 是否需要在测试后重新载入刚才备份的数据 */ protected boolean needRestore = false;
/** * 备份文件的路径, * 如果为空,默认为test/dbunitData/myTestData.xml/ */ protected String xmlFilePath = null;
/** * 需要备份的数据库Table名 */ protected String[] tableNames = null;
public DAOTestCase() { //设了这个,就能autowire by name,否则by setter. setPopulateProtectedVariables(true);
contexts = new ArrayList<String>(); contexts.add("/applicationContext-Hibernate.xml"); contexts.add("/applicationContext-SetupService.xml"); }
public String[] getConfigLocations() { String[] tmp = new String[contexts.size()]; return contexts.toArray(tmp); }
public void onSetUp() throws Exception { if (needBackup) { DbUtil dbUtil = new DbUtil(applicationContext); dbunitConn = new DatabaseConnection(dbUtil.getConn(), "LH"); if (xmlFilePath == null) xmlFilePath = "test/dbunitData/myTestData.xml";
if (tableNames != null) { ITableFilter filter = new DatabaseSequenceFilter(dbunitConn, tableNames); IDataSet dataset = new FilteredDataSet(filter, dbunitConn.createDataSet());
File f_file = new File(xmlFilePath); new File(f_file.getParent()).mkdirs(); XmlDataSet.write(dataset, new FileOutputStream(f_file));
} else { throw new Exception("your choice backup data but no table names asign"); }
} }
public void onTearDown() throws Exception {
if (needRestore) { if (dbunitConn == null) { DbUtil dbUtil = new DbUtil(applicationContext); dbunitConn = new DatabaseConnection(dbUtil.getConn(), "LH"); } IDataSet dataSet = new XmlDataSet(new FileInputStream(xmlFilePath)); DatabaseOperation.REFRESH.execute(dbunitConn, dataSet); } dbunitConn.close();
}
} 子类的代码 package com.itorgan.xxx;
import com.itorgan.lherp.dao.CarDAO; import junit.framework.Test; import junit.framework.TestSuite;
public class CarDAOImplTest extends DAOTestCase { protected CarDAO carDAO; //声明为protected并且和Context,就会被动态注入
public void onSetUp() throws Exception {
}
public void testGetGoodses() throws Exception { carDAO.getValidCars(); }
public static Test suite() { return new TestSuite(CarDAOImplTest.class); } }