首页  ·  知识 ·  测试
如何编写干净的单元测试用例
佚名  本站原创  综合  编辑:dezai  图片来源:网络
篇首语 本文假设读者已经熟悉单元测试及JUnit工具的使用,如果对单元测试及JUnit尚不了解请先学习单元测试及JUnit工具的相关知识。读者
篇首语

    本文假设读者已经熟悉单元测试及JUnit工具的使用,如果对单元测试及JUnit尚不了解请先学习单元测试及JUnit工具的相关知识。读者最好对Spring框架及Spring框架提供的单元测试支持有所了解,因为本文案例基于Spring技术编写。但对Spring不了解并不影响本文所讲述的单元测试用例编写及回调模式、模板方法的应用。

    单元测试是编写高质量代码的前提,通过编写有效的单元测试即可以保证代码的质量又可以提高开发速度,因为大多数问题都可以通过单元测试发现并解决而不需要部署到应用服务器。纵览网上流行的优秀开源框架,无一不提供完整的单元测试用例。Spring框架便是其中的代表和佼佼者,因为Spring所遵循的控制反转(IoC)和依赖注入(DI)原则使编写有效、干净的单元测试用例变得更加方便、快捷。

    编写单元测试用例 

    本文所采用的案例非常简单,就是对数据库表的增、删、改、查操作进行测试。假设我们有这样一个表url(MySql数据库):

    正如你所见,该表只有几个字段,但对于我们的案例来说完全够用。

    看到此处,你应该清楚我们是要对数据库操作进行单元测试。如果你是一位经验丰富的开发人员,此时已经会有许多疑问,甚至已经失去继续阅读本文的兴趣:

    ²  单元测试不应该直接操作数据库?

    ²  对数据库操作的单元测试可以采用DAO模式,Mock一个实现类?

    ²  使用内存数据库?

    ²  其他?

 


    数据库表有了,我们接下来编写DAO及其实现类:

    DAO接口:

/**
* @author tao.youzt
*/
public interface BizUrlDAO {
public Object insert(BizUrlDO bizUrlDO);
public int delete(String url);
public BizUrlDO getByUrl(String url);
}
 

    DAO实现类,该类继承一个支持类,封装了对数据库的操作。

/**
* @author tao.youzt
*/
public class BizUrlIbatisImpl extends GodzillaDaoSupport implements BizUrlDAO {
private static final String GET_BY_URL = "SELECT-BIZ-URL";
private static final String DELETE     = "DELETE-BIZ-URL";
private static final String INSERT     = "INSERT-BIZ-URL";
public int delete(String url) {
return this.delete(DELETE, url);
}
public BizUrlDO getByUrl(String url) {
return this.queryForObject(GET_BY_URL, url, BizUrlDO.class);
}
public Object insert(BizUrlDO bizUrlDO) {
return this.insert(INSERT, bizUrlDO);
}
}
    DO领域对象


/**
* @author tao.youzt
*/
public class BizUrlDO {
private int    id;
private String url;
private String email;
private String name;
// getter and setter
}
    因为本文案例使用Spring作为底层框架,因此这里需要编写Spring配置文件对DAO进行组装。

    Godzilla-dao.xml

 

Godzilla-db.xml

    DAO及其配置文件都已经准备完毕,我们接下来编写测试用例。Spring为单元测试提供了很多有用的支持类,我们在这里使用的是:

    该类提供了POJO属性自动注入的能力,只要为为你的属性字段提供一个Set方法即可。下面我们来看完整的测试用例:

/**
* @author tao.youzt
*/
public class TestBizUrlDAO extends AbstractDependencyInjectionSpringContextTests {
private BizUrlDAO bizUrlDAO;
@Override
protected String[] getConfigLocations() {
return new String[]{"godzilla-dao.xml","godzilla-db.xml"};
}
public void testInsert(){
bizUrlDAO.insert(generateDO());
assertNotNull(bizUrlDAO.getByUrl("www.easyjf.com"));
}
public void testDuplicateInsert(){
bizUrlDAO.insert(generateDO());
try{
bizUrlDAO.insert(generateDO());
assertFalse("Must throw an exception!",true);
}catch(Exception e){
assertTrue(true);
}
}
public void testDelete(){
bizUrlDAO.insert(generateDO());
assertNotNull(bizUrlDAO.getByUrl("www.easyjf.com"));
bizUrlDAO.delete("www.easyjf.com");
assertNull(bizUrlDAO.getByUrl("www.easyjf.com"));
}
private BizUrlSynchronizeDO generateDO() {
BizUrlDO bizUrlDO = new BizUrlDO();
bizUrlDO.setUrl("www.easyjf.com");
bizUrlDO.setName("EasyJWeb");
bizUrlDO.setEmail("webmaster@easyjf.com");
return bizUrlDO;
}
public void setBizUrlDAO(BizUrlSynchronzieDAO bizUrlDAO) {
this.bizUrlDAO = bizUrlDAO;
}
}
getConfigLocations()方法为AbstractDependencyInjectionSpringContextTests 提供配置,Spring会根据该配置文件自动注入bizUrlDAO属性。testInsert()方法用于测试插入新数据,注意这里有个问题,如果数据库中已经存在该URL的记录,则应用会报错,所以这里还要进行数据清除准备处理,我们称之为“测试环境准备”,以后会用到该名词;testDuplicateInsert()方法用于测试插入重复数据的情况,该方法同样存在上面的问题;testDelete()方法用于测试删除数据的情况,这里尽管准备了数据,但仍没有考虑数据库中已经有记录的情况。

    综上所述,尽管该测试类已经比较清晰,但仍然存在许多不足之处。我们将在后面的章节进行详细分析,并给出解决方案。

Callback Function & Template Method  Pattern

    回调函数(Callback Function)和模板方法(Template Method)是软件架构设计中最常用的两种设计模式,这两种设计模式在Spring框架中随处可见。

    关于本节是否要详细介绍回调函数(Callback Function)和模板方法(Template Method)模式的问题,笔者考虑了很长时间。因为网络上对这两种普遍使用的设计模式的定义层出不穷,各有各的道理,很难说谁是谁非。况且,针对不同的应用场景,这两种模式也有许多变体,或者联合使用。

    因此,笔者最终决定不在此处对这两种模式做任何定义或引用,请读者自行参阅相关文档资料。

    回调函数和模板方法模式在单元测试中的应用

    上一节我们简单的回顾了回调函数和模板方法模式,Spring框架中大量采用了这两种设计模式,有兴趣的读者可以阅读Spring框架代码进一步巩固对这两种模式的理解和运用。本节将结合回调函数模式和模板方法模式对前面的测试用例进行重构,读者可以在重构过程中逐步了解这两种设计模式的运用。

本文作者:佚名 来源:本站原创
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读