数据库测试策略
心得一
目前,最有效的方法是利用脚本来重建数据库。测试前去drop表,然后create表,然后再进行测试。
心得二
每一个开发人员需要搞一个数据库实例。不能公用一个数据库。这个是显然的。
使用HSQLDB内存数据库作为测试数据库。这样可能会造成一些问题。比如说一些特性在HSQLDB中和在MYSQL, SQLSERVER当中是不一样的,可能在单元测试中通过了,但是不一定会在生产数据库中运行通过。这是一个问题。需要考虑。但,确实是够快,也不会对系统造成什么样的影响,这个确实。
心得三
使用spring的AbstractTransactionalDataSourceSpringContextTests。在每个testcase开始之前,会自动开启一个事务,然后在结束的时候进行事务回滚。
这样就可以隔绝几个测试用例之间的相互干扰。
有很多文章提到,维护数据库的状态,避免几个测试用例之间的相互干扰,非常必要。这样才能够实现测试的自动化,不需要人工干涉。
· public class BaseDAOTestCase extends AbstractTransactionalDataSourceSpringContextTests{
· protected static Log log = LoggerServiceImpl.getLogger();
·
· protected String[] getConfigLocations() {
· return new String[] {"classpath*:/WEB-INF/mPlatform*ApplicationContext.xml"};
· }
·
· protected void flushSession(){
· SessionFactory sessionFactory =
· (SessionFactory)applicationContext.getBean("sessionFactory");
· sessionFactory.getCurrentSession().flush();
· }
· }
·
· public class PersonDAO extends BaseDAOTestCase {
· private PersonDAO personDAO;
· private Person person;
·
· public void setPersonDAO(PersonDAO personDAO) {
· this.personDAO = personDAO;
· }
·
·
· public void onSetUpBeforeTransaction() {
· person = new Person();
· person.setFirstName("Sean");
· person.setLastName("Liu");
· person.setUserName("forever");
· }
·
· public void testSave() {
· personDAO.save(person);
· assertNotNull(person.getId());
· }
·
· public void testGetPerson() {
· personDAO.save(person);
· Person retrievedPerson = personDAO.getPerson(person.getId());
· assertNotNull(retrievedPerson.getId());
· assertEquals(person, retrievedPerson);
· }
·
· public void testRemovePerson() {
· personDAO.save(person);
· person.delete(person);
· flushSession();
· assertNull(personDAO.getPerson(person.getId()));
· }
· }
但是,这样子不是需要进行Spring的相关配置,这样才可以进行DAO的测试?
心得四
测试DAO不如连数据库一起测试吧。因为DAO测试的目的不是DAO接口实现对不对,而是测试是否如你预期的发送了SQL,如你预期的返回了结果集。这个时候你Mock之后,测试就没有意义了。
我认同上面的看法。我不建议测试DAO还采用MOCK实现。当然,去测试业务逻辑层的方法,采用Mock实现是非常有道理的。我只是需要保证我的业务逻辑的API是否正确就可以了。
心得五
DbUnit为数据库驱动的项目提供的一个对JUnit 的扩展!
除了提供一些常用功能,它可以将你的数据库置于一个测试轮回之间的状态,而DBUnit提供了单元测试需要的数据库的数据准备工作。这个是关键的,照我看来。
而这一个工作对于集成测试也是有用的。
虽然DbUnit提供了完整的TestCase基类, 然而由于大部分公司和项目都有基于项目需要的TestCase基类和派生类,我们并不能直接应用!
SpringSide抽出了其核心------数据库数据的准备和回收工作,即org.springside.core.test.support.DataBaseUnitHelper。
1. DataBaseUnitHelper提供了三种数据库连接配置能力。
a. 在classpath根目录下提供DbUnit.properties,这个是缺省的配置方法。
b. 通过给定的properties文件路径配置
c. 通过程序指定Properties对象配置
2. DataBaseUnitHelper采用Excel作为数据库数据的来源。
虽然DbUnit支持多种数据来源,不过根据实践来看,Excel是最容易编辑和获取(大部分的数据库开发工具支持将数据导出为Excel)。
3. DataBaseUnitHelper提供两种数据库数据的配置和回收的应用策略
a. 对于TestCase,在每次Setup时,都先清空数据库,随后插入准备数据
b. 对于TestCase,只在第一次Setup时先清空数据库,随后插入准备数据,而后不在做任何动作。
2. DataBaseHelper在SpringSide的应用
org.springside.core.test.FunctionWithDataBaseTestCase提供了一个例子描述如何应用和封装DataBaseHelper
SpringSide给出的这种使用的例子可以供我们参考。我觉得它提供的策略a很好。和上面的心得一是一致的,我也倾向于在做测试的时候,搞一个测试的数据库,做测试的时候就在这个数据库中进行操作。这和ROR中建立单元测试数据库是同样的思想。
------君临天下,舍我其谁
------