环境:
JUnit 4.4
DBUnit 2.4.2
Spring 2.5.6
mysql-connector-java 5.1.6
ibatis 2.3.4.726
DAO的单元测试少不了数据环境的初始化,DBUnit给了我们一种非常方便的方式来初始化测试数据,从而保证了单元测试的可重复性。
不巧就在前段时间我把Ubuntu给搞坏了,算了暂时就在Windows下开发吧,反正JAVA程序嘛,一般没有可移植的问题。
为了测试方便,定义了一个测试类的抽象类:
package com.demo.dao;
import java.io.FileInputStream;
import javax.sql.DataSource;
import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.IDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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={"/spring-property-test.xml","/spring-dao.xml"})
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)
@Transactional
public abstract class BaseTest {
private IDatabaseTester databaseTester;
@Autowired
private DataSource dataSource;
@Before
public void setUp() throws Exception {
databaseTester = new DataSourceDatabaseTester(dataSource) ;
IDataSet dataSet = new FlatXmlDataSet(
new FileInputStream(getFlatXmlDataSetPath()));
databaseTester.setDataSet(dataSet);
// will call default setUpOperation
databaseTester.onSetup();
}
@After
public void tearDown() throws Exception {
// will call default tearDownOperation
databaseTester.onTearDown();
}
public abstract String getFlatXmlDataSetPath();
}
其它的测试类只需要继承这个抽象类,实现getFlatXmlDataSetPath()这个方法,在加上想要的测试方法就可以了,比如:
package com.demo.dao;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.demo.Function;
public class FunctionDAOTest extends BaseTest {
@Autowired
private FunctionDAO functionDAO;
@Override
public String getFlatXmlDataSetPath() {
return "src/test/resources/dataset-function.xml";
}
@Test
public void testGetFunction() throws Exception {
//data initialized from dataset-function.xml
Function func;
func = functionDAO.getFunction(1);
assertTrue(func.getFunctionName().equals("admin"));
func = functionDAO.getFunction(2);
assertTrue(func.getFunctionName().equals("checker"));
func = functionDAO.getFunction(3);
assertTrue(func.getFunctionName().equals("tester"));
}
@Test
public void testGetAllFunctions() throws Exception {
//data initialized from dataset-function.xml
List<Function> list = functionDAO.getAllFunctions();
assertTrue(list.size()==3);
Function func;
func = list.get(0);
assertTrue(func.getFunctionName().equals("admin"));
func = list.get(1);
assertTrue(func.getFunctionName().equals("checker"));
func = list.get(2);
assertTrue(func.getFunctionName().equals("tester"));
}
}
不错,真是方便,运行的非常好。
前两天,我在我的移动硬盘上安装了ubuntu8.10,终于又可以在linux下开发了。有了单元测试就是好,立刻可以测试程序是否正常。结果一运行,居然全失败了!
查看日志文件,其中有:
org.dbunit.dataset.NoSuchTableException: Did not find table 'FUNCTION' in schema 'null'
奇怪了,我的表名是小写的function, 我查遍了所有的配置文件,均确认是小写的function,那它为啥要找大写的呢?由于Windows是不区分大小写文件名的,所以一定不会有这个问题。
Google了半天,最后还是在dbunit的网站上找到了线索,参见:http://www.dbunit.org/properties.html
其中写道DatabaseConfig有个参数叫“Case sensitive table names” ,缺省值为false,具体描述为:
Enable or disable case sensitive table names. If enabled, Dbunit handles all table names in a case sensitive way.
原来缺省为大小写不敏感,而且它把表名转换成大写了。
一研究代码,不会改。DatabaseConfig是从connection来的,而我用的是DataSourceDatabaseTester,程序中不直接操作connection,只好再次google了。
原来可以写个匿名类重载DataSourceDatabaseTester的getConnection()方法,参见:http://forum.springsource.org/showthread.php?t=64445
把实例化DataSourceDatabaseTester的代码改为:
databaseTester = new DataSourceDatabaseTester(dataSource) {
public IDatabaseConnection getConnection() throws Exception {
IDatabaseConnection connection = super.getConnection();
connection.getConfig().setFeature(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES , true);
return connection;
}
};
一切都正常了!