`
yh_private
  • 浏览: 38786 次
  • 性别: Icon_minigender_1
  • 来自: 长春
最近访客 更多访客>>
社区版块
存档分类
最新评论

关于测试facade的一点想法

阅读更多
很肤浅的想法,希望大牛多多指点

原来的façade代码
public class XxFacadeImpl implements XxFacade {
    public List doSomeThing(String param1) {
        //1组装查询条件
        XXVO xxVO=new XXVO();
        xxVO.setParam(param);
        //2.通过条件查询数据库已获得相业务数据
        List xxList = xxDao.getXXList(xxVO);        //Dao逻辑1
        //3.基于xxList的业务计算
		XXVO xxVO1 = new XXVO();              //业务逻辑1
        For(int i=0;i<xxList.size();i++){
			xxVO1 = (XXVO) xxList.get(i);
			xxVO1.setName(String.valueOf(i));
}                          
        //4.把计算结果更新到数据库
        xxDao.updateXXList(xxList);                 //Dao逻辑
        //5.做其他事                               //业务逻辑 2     
        return xxList;
    }
}

这样的代码很常见,但是这样把业务代码和持久层方法调用写在一起的方法却很难被测试,如果想测试这样的方法大概的流程如下
1. 在数据库中准备符合条件的数据(insert)符合param1的查询条件
2. 调用XxFacadeImpl的doSomeThing(1)方法
3. 得到返回的List 验证业务逻辑1是否正确
对于这样的代码可以勉强测试,但是却相当麻烦,首先要建立测试数据,要想着自己所查询的表是否有关联,如果有还要一同插入测试数据,否则Dao逻辑1将不能得到数据,导致测试失败,测试之后还需要把数据回滚,不然数据库中就会留下垃圾数据。
很明显我们的façade并不关心Dao的实现或者表中的数据,但为了测试这个方法却要模拟这样一个环境。然而对于业务逻辑2中的代码我们如何测试呢?这只是一个勉强可以测试的Façade方法因为他所操作的数据正好是这个方法的返回值,我们简单修改一下这段代码
public class XxFacadeImpl implements XxFacade {
    public boolean doSomeThing(String param1) {
        //1组装查询条件
        XXVO xxVO=new XXVO();
        xxVO.setParam(param);
        //2.通过条件查询数据库已获得相业务数据
        List xxList = xxDao.getXXList(xxVO);        //Dao逻辑1
        //3.基于xxList的业务计算
		XXVO xxVO1 = new XXVO();              //业务逻辑1
        For(int i=0;i<xxList.size();i++){
			xxVO1 = (XXVO) xxList.get(i);
			xxVO1.setName(String.valueOf(i));
}                          
        //4.把计算结果更新到数据库
		//upadateXXList(xxList)将返回更新是否成功
        return xxDao.updateXXList(xxList);            
    }
}

只是简单的修改了一下方法的返回值,我们现在只关心这个update 方法是否成功.
那怎么才能测试业务逻辑1呢?

总结一下,
不可测试方法:这样的Façade很难被测试,甚至有些部分不能被测试或方法中的逻辑根本不能被测试,
垃圾数据:会在数据库中留下大笔的垃圾数据,虽然可以通过继承TestDaoConstant来自动回滚,但Façade业务本身是不需要事务的,如果引入mock来做孤立测试,Mock带来的复杂度也将被引入。
代码复用:这样的代码通常很难被复用。
测试覆盖度:由于方法中有不可测试部分也就不能保证测试的覆盖度。


改良的Façade编码如下

public class XxFacadeImpl implements XxFacade {
    public boolean doSomeThing(String param1) {
        //1组装查询条件
        XXVO xxVO=new XXVO();
        xxVO.setParam(param);
        //2.通过条件查询数据库已获得相业务数据
        List xxList = xxDao.getXXList(xxVO);        //Dao逻辑1
        //3.基于xxList的业务计算
editUserName(xxList);		                //业务逻辑1
        //4.把计算结果更新到数据库
        xxDao.updateXXList(xxList);                 //Dao逻辑
        //5.做其他事                               //业务逻辑 2  
		someBusiness2(xx);
        return true;
}
public List editUserName(List xxList){
		XXVO xxVO1 = new XXVO();              //业务逻辑1
        for(int i=0;i<xxList.size();i++){
			xxVO1 = (XXVO) xxList.get(i);
			xxVO1.setName(String.valueOf(i));
}  
return xxList;
}

public List someBusiness2(xxx){
	...
	…
	…
	…
return result;
}
}


这样的代码XxFacade中doSomeThing方法并不关心业务逻辑的具体实现,只是这个逻辑的实现流程,他只是调用一些纯业务方法,而这些纯业务方法又不需要依赖Dao数据我们随便组装一个List就可以测试,我们不再需要数据库,也摆脱了事务,需要测试的只是这些干干净净的纯业务方法,他们只依赖简单的参数,返回这个业务操作后的数据。至于XxFacade中doSomeThing方法我们甚至不需要去测试他,他所调用的方法全部是测试过的可信赖方法

看看简单的改动为我们带来了什么?
1. 使方法可测试,提高测试覆盖度
2. 让Façade可以脱离事务,数据库进行测试
3. 有效的拆分方法,每个方法的业务都很简单,一屏足已装下
4. 保证每个纯业务方法都只做一件事。
5. 提高方法被复用的机会
由于方法doSomething中所调用的全部是可信任方法,也就直接提高代码的质量和覆盖度,增加了重构的勇气。

最后希望大家可以多多提交有效的测试程序,提高我们代码的质量,下班前跑遍测试看到著名的green bar回家睡个安稳觉。
分享到:
评论
1 楼 Joo 2008-07-01  
不知道你说的将Mock的复杂度也带入其中具体是指什么

相关推荐

    Laravel开发-symfonys-facade

    因此,尽管Facade在很多场景下非常实用,但在编写复杂或需要高度测试的代码时,可能会考虑使用依赖注入。 综上所述,Laravel中的Symfony's Facade是实现高效开发的重要工具,它将Symfony组件与Laravel的优雅编程...

    FACADE模式

    **外观(Facade)模式**是一种结构型设计模式,它的主要目的是提供一个统一的接口,用于客户端访问复杂的子系统。在大型软件系统中,通常由多个模块或子系统组成,每个子系统都有自己的功能,而客户端可能需要与这些...

    Facade模式

    **外观(Facade)模式**是软件工程中一种常用的设计模式,属于结构型模式。它提供了一个统一的接口,用于访问子系统中的一组接口。Facade模式使得子系统更易于使用,降低了客户端与复杂子系统之间的耦合度。在Java...

    C++ Facade模式

    **C++ Facade模式** Facade模式,又称为外观模式,是设计模式中的一种结构型模式。在软件工程中,它为子系统提供了一个统一的入口,简化了客户端对复杂子系统的访问,使得客户端无需了解子系统内部的具体实现细节。...

    设计模式之外观模式 facade

    外观模式(Facade Pattern)是设计模式中的一种结构型模式,主要目的是为了解决复杂的系统接口问题,提供一个简单的统一入口,使得客户端可以更方便地使用系统。在Java中,外观模式通常用来隐藏系统的复杂性,对外只...

    java实现的简单的应用facade模式范例

    在这个Java实现的简单应用中,`facadeclient`可能是一个运行上述代码的测试类,用来验证Facade模式的正确性和功能。类图则会展示这些类之间的关系,包括Facade如何封装和调度子系统对象。 总结来说,Facade模式在...

    session facade:基于在线式银行的应用

    Session Facade是一种设计模式,常用于企业级Java应用程序,特别是在EJB(Enterprise JavaBeans)环境中,目的是解决上述问题,提高系统性能、可维护性和可扩展性。在基于在线式银行的应用中,Session Facade扮演着...

    设计模式之Facade

    eclipse工程文件 包含代码 有助理解 门面(Facade)模式 &lt;br&gt;外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式。 &lt;br&gt;医院的例子 &lt;br&gt;用一个例子进行说明,如果把医院...

    facade设计模式

    ### Facade设计模式详解 #### 一、简介 在软件工程领域,设计模式是一种被广泛认可的解决特定问题的方法论。其中,`Facade设计模式`(外观模式)是一种结构型设计模式,它通过提供一个统一的接口来隐藏系统的复杂...

    Command和Facade设计模式

    在软件设计模式的世界里,`Command`(命令)和`Facade`(外观)模式是非常重要的两种设计模式。它们分别服务于不同的目的,但都是为了提高代码的可读性、可维护性和灵活性。 `Command`模式是一种行为设计模式,它将...

    设计模式之门面模式(Facade模式)

    设计模式之门面模式(Facade模式),介绍门面模式,实际例子分析,代码讲解等

    Ajax中使用Facade外观模式的Eclipse版本的Demo

    **Ajax与Facade模式** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术允许我们创建交互性更强、响应更快的网页。它通过在后台与服务器进行少量数据交换,实现了页面的部分更新,而无需刷新整个页面。...

    外观模式facade

    外观模式(Facade)是设计模式中的一种结构型模式,它为复杂的系统或子系统提供了一个统一的入口点,简化了客户端与系统之间的交互。通过外观模式,我们可以将系统的内部复杂性隐藏起来,使得用户只需要与一个简单的...

    Wrapper facade pattern

    **包装器外观模式(Wrapper Facade Pattern)** 包装器外观模式是一种软件设计模式,它将一个复杂的组件或者一组组件的接口进行简化,提供一个统一的、更易用的访问方式。这种模式通常用于隐藏底层系统的复杂性,为...

    Facade模式_Java源代码

    实验内容: 1) 家庭影院中有CD机,DVD机,收音机Turner,录影机Recorder,功放Amplifier,升降屏幕Screen等,请为家庭影院系统设计一个请设计一个门面,通过它可以方便的操作...2) 编写一个测试主类,测试你的程序。

    simple log facade for java

    SLF4J(Simple Logging Facade for Java)是Java中的一种日志抽象层,它为各种日志框架提供了一个统一的接口,例如Log4j、Java Util Logging (JUL)、Logback等。这个设计使得开发者可以在不修改代码的情况下更换底层...

    设计模式1,FACADE模式,Adapter

    本文将深入探讨FACADE模式、Adapter模式以及Singleton和Proxy模式的基本概念、应用场景和关键要素。 首先,FACADE(外观)模式是一种接口型模式,它的主要作用是为复杂的子系统提供一个简单的接口,使得客户端无需...

Global site tag (gtag.js) - Google Analytics