dbunit进行数据库操作的测试
j2ee程序好多都涉及到了数据库操作,这时进行mock测试就没有意义,不如直接在数据库上进行操作.
进行数据库测试有两点要求
1测试之前数据库要处在一个确定性的状态下.
2测试不改变数据库的状态.
我觉得比较好的方法是建立一个专用的测试数据库,避免了测试数据的干扰.否则每次测试结束就要进行相应的现场恢复.
假设我们有个开发数据库allcrap,然后建立个测试数据库allcrap_test.为了保证数据库表结构的一致,可以人工同步,也可以用mysqldump进行
.\mysqldump.exe-uroot-prootallcrap-d>ddl.sql
这个命令导出了allcrap数据库DDL语句,-d选项是表示不用导出数据,然后把DDL语句导入测试库即可.
.\mysql-uroot-prootallcrap_test<ddl.sql
数据库结构同步以后,要将数据库中的数据达到一个确定的状态,可以用dbunit的DataSet来实现.
DataSet对应了数据库中里的数据,可以将数据库初始化.
allcrap数据库里有个表product,ddl是
CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `price` decimal(10,2) NOT NULL, `vender_id` int(11) DEFAULT NULL, `optlock` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `product_fk_vendor_id` (`vender_id`), CONSTRAINT `product_fk_vendor_id` FOREIGN KEY (`vender_id`) REFERENCES `vendor` (`id`) ) ENGINE=InnoDB
对应的dataset就是
<dataset> <product name="旭日笔记本" price="3699" id="1" optlock="0"/> <product name="速龙 3200+" price="400" id="2" optlock="0"/> <product name="佳能打印机" price="600" id="3" optlock="0"/> </dataset>
这样dbunit就能在每个测试之前把数据库的product表初始化为这三条数据.
随后的每一个测试是建立在确定性的状态上,也就能够用程序来进行自动化测试,而不用人工干预.
这样每天都可以用定时任务进行测试.
一个dbunit的testcase如下
public class ProductDaoTest extends DBTestCase { public ProductDaoTest() { System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "com.mysql.jdbc.Driver"); System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "jdbc:mysql://localhost/allcrap_test"); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "root"); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "root"); } @Override protected IDataSet getDataSet() throws Exception { return new FlatXmlDataSetBuilder().build(new FileInputStream( ".\\bin.\\product_dataset.xml")); } private ProductDao productDao; private SessionFactory sessionFactory; private Session session; @Override protected void setUp() throws Exception { super.setUp(); sessionFactory = new Configuration() .configure("hibernate_test.cfg.xml").buildSessionFactory(); this.session = sessionFactory.openSession(); productDao = new ProductDao(); productDao.setSession(session); } @Override protected void tearDown() throws Exception { if (this.session != null) { this.session.close(); } if (this.sessionFactory != null) { this.sessionFactory.close(); } super.tearDown(); } private void beginTx() { this.session.beginTransaction(); } private void commit() { this.session.getTransaction().commit(); } @Test public void testBasicCRUD() { this.beginTx(); Product p = this.productDao.load(2); assertEquals(Integer.valueOf(2), p.getId()); Product newProduct = new Product(); newProduct.setName("testProduct"); newProduct.setPrice(BigDecimal.valueOf(34.2)); this.productDao.save(newProduct); this.commit(); try { assertEquals("testProduct", this.getConnection() .createDataSet().getTable("product").getValue(3, "name")); } catch (Exception e) { e.printStackTrace(); } } @Test public void testProductListByPrice() { this.beginTx(); List<Product> productList = this.productDao.findProductListByPrice( new BigDecimal(400), new BigDecimal(600)); assertEquals(2, productList.size()); assertEquals(Integer.valueOf(2), productList.get(0).getId()); assertEquals(Integer.valueOf(3), productList.get(1).getId()); this.commit(); } }