`
wuhua
  • 浏览: 2110460 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

单元测试之实践二,关于DAO的测试

阅读更多
       前阵子发表过 我的第一个真正意义上的测试
里面对于测试Service大家是没有意义的,对于测试DAO层则表现各有各的看法。
比如
robbin     大哥建议:

测试DAO不如连数据库一起测试吧。因为DAO测试的目的不是DAO接口实现对不对,而是测试是否如你预期的发送了SQL,如你预期的返回了结果集。这个时候你Mock之后,测试就没有意义了。

hyysguyang      大哥建议:篇
wuhua 写道
分层的原因很多。这里我的看法片面就不说了
但对于mock来说是有莫大好处的。
比如service测试的时候完全可以做到隔离数据库,

我现在的意思是,
居然Service可以隔离Dao层,也就是说Dao层也是可以做到隔离相关的数据实现的。也是可以mock一个对象。而并非用实际的连接去代 替。如果我们的逻辑没出错的话,测试就算通过了,至于数据层的检测,那就不关我们的事情了,比如Hibernate由Hibernate去test, Spring由Spring去Test,Oracle由它自己去做。干自己的事情,别趟其他浑水。这样不是潇洒很多吗

但是数据库的测试毕竟比较特殊,记住测试的目的是确保你的代码质量,如果你确定你的这样测就没问题了,那无话可说,否则就尽量多的测试。
事实上,最原始的单元测试(plain testcase)就是用来测方法,测业务逻辑的,如果有逻辑就测,没逻辑就不用测了,同样的道理,相信你不会去测一个bean的get/set方法吧。
记住你测试的目的和动机,如果你认为测试dao层是为了测你的逻辑(你确定你的dao的实现代码是否真的存在逻辑),那你就mock吧,但是,我 们更相信,我们测DAO层,更应该是测访问数据库的情况,你如连接,sql是否正确,sequence是否正确等,而这些你必须要真正的连接数据库,也因 此,我们一般都是直接访问数据库来测试的,当然,如果可能你可以采用内存库。
事实上,我们对dao的测试,一般都进行所谓的的集成单元测试。我认为,你应该确定好你的测试策略,然后在去采用相应的测试方法。我在目前的开发中就是采用这样的方式测的。

上面两个大哥都建议测试DAO的时候还是连接数据库为好。
但个人认为上面两个大哥的单元测试以非纯正的单元测试了,而是集成单元测试。
其实说白了,测试这东西只是为了项目更好,更快的完成。至于是否要求纯单元,或者是集成单元测试,则看各位的需要,如果觉得集成单元测试对项目有帮助,那就用吧,现在发现对这个已经没有明显的界限了。


不理会它了,现在回归到我们用户注册的例子。
java 代码
 
  1. 1public interface IAccountDao extends IBaseDao {    
  2. 2.     public Account findAccountById(String id);    
  3. 3.     public Account findAccounByName(String name);    
  4. 4. }   

实际实现代码
java 代码
 
  1. package org.wuhua.dao.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.wuhua.dao.IAccountDao;  
  6. import org.wuhua.model.Account;  
  7.   
  8. public class AccountDao extends BaseDao implements IAccountDao {  
  9.   public Account findAccountById(String id) {  
  10.         return (Account) this.getHibernateTemplate().get(Account.class, id) ;  
  11.     }  
  12.   
  13.     public Account findAccounByName(String name) {  
  14.         List l = this.getHibernateTemplate().find("from Account as a where a.name=?", name);  
  15.         if(l != null && l.size() >=1)  
  16.             return (Account) l.get(0);  
  17.         else   
  18.             return null;  
  19.     }  
  20. }  

java 代码
 
  1. package org.wuhua.dao;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import junit.framework.Assert;  
  7. import junit.framework.TestCase;  
  8.   
  9. import org.easymock.MockControl;  
  10. import org.easymock.classextension.MockClassControl;  
  11. import org.springframework.orm.hibernate3.HibernateTemplate;  
  12. import org.wuhua.dao.impl.AccountDao;  
  13. import org.wuhua.model.Account;  
  14.   
  15.    
  16.   
  17. public class AccountDaoTest extends TestCase {  
  18.       
  19.     private AccountDao accountDao;  
  20.     private org.springframework.orm.hibernate3.HibernateTemplate ht;  
  21.     private MockControl control;  
  22.   
  23.     protected void setUp() throws Exception {  
  24.         control = MockClassControl.createControl(HibernateTemplate.class);  
  25.         ht = (HibernateTemplate) control.getMock();  
  26.         accountDao = new AccountDao();  
  27.         accountDao.setHibernateTemplate(ht);  
  28.     }  
  29.   
  30.     protected void tearDown() throws Exception {  
  31.            
  32.     }  
  33.       
  34.     public void testFindAccountById(){  
  35.         Account a = new Account("wuhua");  
  36.         a.setId("10");     
  37.           
  38.         ht.get(Account.class, a.getId());  
  39.           
  40.         control.setReturnValue(a);  
  41.           
  42.         control.replay();  
  43.           
  44.         Account result =   accountDao.findAccountById(a.getId());  
  45.           
  46.         assertNotNull(result);  
  47.   
  48.         Assert.assertEquals(a.getId(),result.getId());  
  49.         Assert.assertEquals(a, result);  
  50.           
  51.         control.verify();  
  52.           
  53.     }  
  54.       
  55.     public void testFindAccountByName(){  
  56.         Account a = new Account("wuhua");      
  57.            
  58.         ht.find("from Account as a where a.name=?", a.getName());  
  59.         List l = new ArrayList();  
  60.         l.add(a);  
  61.         control.setReturnValue(l);  
  62.           
  63.         control.replay();  
  64.           
  65.         Account result =  accountDao.findAccounByName(a.getName());  
  66.   
  67.         Assert.assertEquals(a.getId(),result.getId());  
  68.         Assert.assertEquals(a, result);  
  69.           
  70.         control.verify();  
  71.           
  72.     }  
  73. }  
分享到:
评论
13 楼 zaya 2007-09-05  
把测试分类吧。比如分成functional test和checkin test. Checkin是functional的子集,只包含运行速度快的 。  Agile只运行checkin, functional隔的时间长些再运行。

不知道junit能分类不,testng分类很容易。
12 楼 zdonking 2007-09-03  
用了,可是我们的一部分查询和service是在一起的,测service的时候,也就得测dao吧。只mock了关联的service。这种方式大概属于集成单元测试吧。但这样可敏捷不起来啊。运行一个test,可以喝一杯咖啡了 :")
11 楼 wuhua 2007-09-02  
用easymock
10 楼 zdonking 2007-09-02  
4月的帖子了,不知道还有没有人会回,我们的团队尝试曾经了tdd的方式,但最后放弃了,原因有很多,其中一个就是运行测试太慢了.比如,每写一个方法就跑一下该业务方法的测试.但测试在启动的时候会就会很慢,用的是ssh的框架,测试在启动的时候会加载hernate的pojo,以及初始化spring环境中的业务对象,而且由于运用了proxyTargetClass(好像是使用cglib做类代理的)导致启动很慢很慢,有时候可以说让人无法忍受,让人无法敏捷起来.有没有什么好的办法解决.
9 楼 hyysguyang 2007-04-04  
对达到你目标没有任何帮助的测试用例远比没有测试用例还要糟糕,因为那不但浪费时间还浪费金钱……
所以,请确定你的测试目标,然后确定你的测试策略,之后就写有用的测试用例了.
在我开了,TDD除了提高质量之外,还有很多很多的好处,比如对我的开发效率有非常明显的提高.其他的好处嘛,那些很多经典的文章和书籍都介绍过,Just do it,慢慢的去体会咯
8 楼 childpp 2007-03-19  
引用
测试的策略和你用什么编程语言无关。单元测试也不是为了划清界限才产生的,单元测试为了保证软件的质量,这一点不要想歪了。不管是Java还是Ruby,敏捷软件开发有一个理念,所有的人拥有所有的代码,不管代码是不是你经手的,你都有责任去维护它的质量。单元测试不是为了推卸责任。

rails和Java在单元测试这一点上没有什么区别,本版前面有一个关于mock适用场合的讨论,这里不展开谈,只说结论:mock仅仅适用于测试环境无法重现的部分,例如信用卡支付网关,web容器请求和响应对象等等,mock不应该被滥用。

单元测试的范畴并不单单指隔离所有依赖对象进行单个对象的测试,否则任何对象的测试都必须引入mock,否则单元测试就无法完成的。怎么做单元测试要看你的测试目标,如果偏离了测试的目标,一昧追求纯粹意义上的隔离性,测试根本就是做无用功。

完全同意,测试是为了质量,不是为了分清责任
7 楼 robbin 2007-02-09  
引用
由于java是工业化工作
所以别人写的代码的错误
会导至你程序的报错

为了画清界线才产生了单元测试。。。

ROR很少有你不经手的逻辑。。。
TDD也使别人写错的代码很快被发现
所以RAILS不用非要去追求单元测试

而如果是java那么。。。
还是老实作mock
DAO是自己写的的但是框架不是


测试的策略和你用什么编程语言无关。单元测试也不是为了划清界限才产生的,单元测试为了保证软件的质量,这一点不要想歪了。不管是Java还是Ruby,敏捷软件开发有一个理念,所有的人拥有所有的代码,不管代码是不是你经手的,你都有责任去维护它的质量。单元测试不是为了推卸责任。

rails和Java在单元测试这一点上没有什么区别,本版前面有一个关于mock适用场合的讨论,这里不展开谈,只说结论:mock仅仅适用于测试环境无法重现的部分,例如信用卡支付网关,web容器请求和响应对象等等,mock不应该被滥用。

单元测试的范畴并不单单指隔离所有依赖对象进行单个对象的测试,否则任何对象的测试都必须引入mock,否则单元测试就无法完成的。怎么做单元测试要看你的测试目标,如果偏离了测试的目标,一昧追求纯粹意义上的隔离性,测试根本就是做无用功。
6 楼 抛出异常的爱 2007-02-09  
robbin 写道
其实连接真实数据库进行DAO测试速度并不慢,这是因为每个DAO测试结束后,会自动rollback恢复环境。

对于一些框架软件,例如springframework来说,要测试的是API实现的逻辑,这种情况下大量mock隔离其他对象的影响是必要的。但是对于我们应用程序,特别是数据处理型应用,你不测试数据库访问,根本就等于没有做测试。换句话说测试DAO就是在测试你的Hibernate映射关系有没有配对,你的HQL查询有没有写对,这一Mock,要测试的真正目标根本就没有达到。

这种DAO测试诚然就是集成单元测试,其实就是对于Web Action测试,我也曾经一度认为应该mock service来测试,但是现在我已经不这样做了,而是真正初始化webwork的容器注入真正的service对象来测试了。因为Action是没有业务逻辑的,测试Action的目标是看xwork.xml有没有配对,拦截器运用是否正确的,这一mock,直接把action对象当做POJO来测试,你只能测试action传了什么参数,其他什么都没有去测,但是action传入什么参数,那是OGNL自动完成的,用不着你多此一举了。

从这个角度来说,只有对util类的测试才是真正的单元测试,其他都是集成测试,但我不觉得这样做有什么不对。特别是我看过ruby on rails的测试框架以后更加坚定了这种做法。rails的unit test,functional test,integration test都是集成测试。
由于java是工业化工作
所以别人写的代码的错误
会导至你程序的报错

为了画清界线才产生了单元测试。。。

ROR很少有你不经手的逻辑。。。
TDD也使别人写错的代码很快被发现
所以RAILS不用非要去追求单元测试

而如果是java那么。。。
还是老实作mock
DAO是自己写的的但是框架不是
5 楼 robbin 2007-02-09  
其实连接真实数据库进行DAO测试速度并不慢,这是因为每个DAO测试结束后,会自动rollback恢复环境。

对于一些框架软件,例如springframework来说,要测试的是API实现的逻辑,这种情况下大量mock隔离其他对象的影响是必要的。但是对于我们应用程序,特别是数据处理型应用,你不测试数据库访问,根本就等于没有做测试。换句话说测试DAO就是在测试你的Hibernate映射关系有没有配对,你的HQL查询有没有写对,这一Mock,要测试的真正目标根本就没有达到。

这种DAO测试诚然就是集成单元测试,其实就是对于Web Action测试,我也曾经一度认为应该mock service来测试,但是现在我已经不这样做了,而是真正初始化webwork的容器注入真正的service对象来测试了。因为Action是没有业务逻辑的,测试Action的目标是看xwork.xml有没有配对,拦截器运用是否正确的,这一mock,直接把action对象当做POJO来测试,你只能测试action传了什么参数,其他什么都没有去测,但是action传入什么参数,那是OGNL自动完成的,用不着你多此一举了。

从这个角度来说,只有对util类的测试才是真正的单元测试,其他都是集成测试,但我不觉得这样做有什么不对。特别是我看过ruby on rails的测试框架以后更加坚定了这种做法。rails的unit test,functional test,integration test都是集成测试。
4 楼 抛出异常的爱 2007-02-09  
hsql在内存里会好一点
那样内存里的逻辑好构造一点
3 楼 badqiu 2007-02-09  
争论那么多干啥,测试的标准就是假如测试通过但你的实际代码不能运行那这个测试就不用写了
所以dao没有测试实际数据库也用不着写测试了
2 楼 dengyin2000 2007-02-09  
比较赞成LZ的想法。连接数据库耗时,而且实际上是又测试了hibernateTemplate 和 hibernate。

1 楼 pupi 2007-02-09  
感觉对dao的单元测试还是应该直接操作数据库呢。
写一个专门给测试用的spring配置文件,在这个文件中配置测试数据库,并且放好初始数据。
对hibernatetemplate类,不mock也可以的。

相关推荐

    SpringBoot 多模块Dao层单元测试

    本篇文章将重点讲解如何在IDEA环境下,针对Spring多模块项目中的Dao层进行单元测试。 首先,我们要理解什么是单元测试。单元测试是一种软件测试方法,它针对程序中的最小可测试单元,如方法或类,进行独立验证。在...

    使用junit测试ssh中的dao

    “junit使用指南及作业规范.pdf”这份文档可能详细介绍了JUnit的用法,包括更复杂的特性如参数化测试、超时测试、假设测试等,以及如何编写良好的测试实践。遵循这些规范可以提高测试的覆盖率和质量。 在实际开发中...

    iOS单元测试最佳实践

    ### iOS单元测试最佳实践 #### 一、iOS单元测试的重要性及意义 在软件开发过程中,单元测试是确保代码质量、提高开发效率的关键环节之一。对于iOS应用开发而言,良好的单元测试不仅能帮助开发者发现并修复潜在的...

    单元测试实践小结(很详细)

    单元测试是一种软件开发中的关键实践,它涉及到对代码的各个最小可测试单元进行独立验证,以确保它们按预期工作。这种测试方法可以帮助开发者在早期发现并修复错误,提高代码质量,减少集成和系统测试阶段的问题。 ...

    使用JUnit进行单元测试PPT

    在Spring框架中进行单元测试,特别是测试DAO层,通常需要准备默认数据和测试数据,并可能需要模拟Spring的IoC容器。尽管Spring推荐使用隔离的测试,但在实际项目中,直接使用Spring框架进行测试可以简化流程。 通过...

    junit测试spring,hibernate的dao层代码

    在软件开发过程中,单元测试是确保代码质量的重要环节。`JUnit` 是Java编程语言中最流行的单元测试框架,它允许开发者...通过这样的测试实践,我们可以更好地维护代码,减少因数据层错误导致的问题,提高整体项目质量。

    hibernate 单元测试批处理代码

    总结,这个项目涉及了使用Hibernate进行单元测试的关键技术和实践,包括配置测试环境、创建和管理测试数据、实施批处理操作以及进行有效的测试验证。理解并掌握这些内容,对于开发高效、健壮的Java应用程序至关重要...

    spring MVC junit 单元测试(controller)

    在Spring MVC框架中,单元测试是确保代码质量的重要步骤,特别是在控制器层(Controller)。...在实际操作时,参考博客中的示例代码和上述步骤,可以更好地理解和实践Spring MVC Controller的单元测试。

    SSH单元测试代码整理

    通过以上描述,我们可以看到SSH框架下的单元测试涉及到多方面的技术和实践,包括对Spring、Struts和Hibernate的理解,以及单元测试的原理和技巧。这两份代码文件为学习和实践这些知识提供了一个很好的起点。

    Spring对于业务层的单元测试支持

    为了确保业务层的正确性,我们还需要关注数据访问对象(DAO)的测试。Spring Data JPA提供了`@Query`注解,允许自定义SQL或HQL查询,而在测试中,我们可以利用`@Sql`和`@SqlGroup`注解执行SQL脚本,预先填充或清理...

    单元测试之道Java版:使用JUnit

    《单元测试之道Java版:使用JUnit》是一本深入讲解如何在Java开发中运用JUnit进行单元测试的专业书籍。单元测试是软件开发过程中的重要环节,它能够确保代码的正确性,提高代码质量,以及便于后期的维护和重构。...

    对DAO编写单元测试[1]

    编写对DAO编写单元测试[1]软件测试单元测试作为保证软件质量及重构的基础,早已获得广大开发人员的认可。单元测试是一种细粒度的测试,越来越多的开发人员在提交功能模块时也同时提交相应的单元测试。对于大多数开发...

    使用Unitils测试DAO

    标题“使用Unitils测试DAO”涉及的是在Java开发中如何利用Unitils库来高效地测试数据访问对象(DAO)层的代码。...这种测试方法有助于提升代码质量,确保数据库操作的正确性,并遵循良好的测试实践。

    SpringMvc单元测试Junit

    SpringMvc单元测试Junit是Java开发中的重要实践,主要用于确保应用程序的特定部分,如控制器,服务或DAO,按预期工作。在这个Demo中,我们将深入探讨SpringMvc如何与JUnit结合进行有效的单元测试,以及如何利用这些...

    对dbunit进行mybatis DAO层Excel单元测试(必看篇)

    五、Dbunit测试实践 在mybatis DAO层中,可以使用dbunit来进行单元测试。首先,需要在pom.xml文件中添加相关的依赖项,然后创建一个unitils.properties配置文件,用于配置自定义拓展模块,数据加载等相关信息。接着...

    mybatis项目源码及单元测试

    通过对 Mybatis-Demo 的源码分析和单元测试实践,我们可以深入了解 MyBatis 的工作机制,提升我们的编程和测试技能。在实际开发中,理解并掌握这些知识点将有助于我们写出更加高效、稳定的代码。

    使用junit进行单元测试, 包含项目源码及笔记

    在进行单元测试时,遵循一些最佳实践能提高测试质量: 1. **测试隔离**:每个测试应独立于其他测试,避免共享状态,确保每次运行的结果一致。 2. **测试覆盖率**:尽可能覆盖代码的所有分支和边界条件,确保代码的...

Global site tag (gtag.js) - Google Analytics