数据库测试策略

心得一

       目前,最有效的方法是利用脚本来重建数据库。测试前去drop表,然后create表,然后再进行测试。

心得二

       每一个开发人员需要搞一个数据库实例。不能公用一个数据库。这个是显然的。

       使用HSQLDB内存数据库作为测试数据库。这样可能会造成一些问题。比如说一些特性在HSQLDB中和在MYSQL, SQLSERVER当中是不一样的,可能在单元测试中通过了,但是不一定会在生产数据库中运行通过。这是一个问题。需要考虑。但,确实是够快,也不会对系统造成什么样的影响,这个确实。

心得三

       使用springAbstractTransactionalDataSourceSpringContextTests。在每个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. DataBaseHelperSpringSide的应用

 org.springside.core.test.FunctionWithDataBaseTestCase提供了一个例子描述如何应用和封装DataBaseHelper

       SpringSide给出的这种使用的例子可以供我们参考。我觉得它提供的策略a很好。和上面的心得一是一致的,我也倾向于在做测试的时候,搞一个测试的数据库,做测试的时候就在这个数据库中进行操作。这和ROR中建立单元测试数据库是同样的思想。



------君临天下,舍我其谁------