`
luogankun
  • 浏览: 18892 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

junit设计模式分析二(模板方法模式)

阅读更多

在实际的测试中,为了测试业务逻辑,必须构造一些参数或者一些资源,然后才可进行测试,最后必须释放这些系统资源。如测试数据库应用时,必须创建数据库连接Connection,然后执行操作,最后必须释放数据库的连接等。如下代码:

public void testUpdate(){
	// Load the Oracle JDBC driver and Connect to the database
	DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
	String url = "jdbc:oracle:thin:@localhost:1521:ORA91";
	Connection conn = DriverManager.getConnection (url, "hr", "hr");
	// Select first_name and last_name column from the employees table
	ResultSet rset = stmt.executeQuery ("select FIRST_NAME, LAST_NAME from EMPLOYEES");
	……………
	// Disconnect
	conn.close ();
}

 其实这种情况很多,如测试EJB时,必须进行JNDI的LookUp,获得Home接口等。可是如果在一个TestCase中有几个测试方法,例如测试对数据库的Insert,Update,Delete,Select等操作,这些操作必须在每个方法中都首先获得数据库连接connection,然后测试业务逻辑,最后再释放连接。这样就增加了测试人员的工作,反复的书写这些代码,与JUnit当初的设计目标不一致?怎样解决这个问题?

 

接下来要解决的问题是给开发者一个便捷的“地方”,用于放置他们的初始化代码,测试代码,和释放资源的代码,类似对象的构造函数,业务方法,析构函数一样。并且必须保证每次运行测试代码之前,都运行初始化代码,最后运行释放资源代码,并且每一个测试的结果都不会影响到其它的测试结果。这样就达到了代码的复用,提供了测试人员的效率。
Template Method(模板方法)可以比较好得解决这个的问题。摘引其意图,“定义一个操作中算法的骨架,并将一些步骤延迟到子类中。Template Method使得子类能够不改变一个算法的结构即可重新定义该算法的某些特定步骤。”这完全恰当。这样可以使测试者能够分别来考虑如何编写初始化和释放代码,以及如何编写测试代码。不管怎样,这种执行的次序对于所有测试都将保持相同,而不管初始化代码如何编写,或测试代码如何编写。

 

 

模板方法的构成:

1、AbstractClass 定义多个抽象操作,以便让子类实现。并且实现一个具体的模板方法,它给出了一个顶级逻辑骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类里实现。模板方法也有可能调用一些具体的方法。
2、ConcreteClass 实现父类的抽象操作方法,它们是模板方法的组成步骤。每一个AbstractClass可能有多个ConcreteClass与之对应,而每一个ConcreteClass分别实现抽象操作,从而使得顶级逻辑的实现各不相同。

 

模板方法模式代码的实现:

Template:

public abstract class Template {
	public void template() {
		this.method1();
		this.method2();
		this.method3();
	}
	
	public abstract void method1();
	public abstract void method2();
	public abstract void method3();
}

 

ConcreteTemplate:

public class ConcreteTemplate extends Template{

	@Override
	public void method1() {
		System.out.println("method1");
	}

	@Override
	public void method2() {
		System.out.println("method2");
	}

	@Override
	public void method3() {
		System.out.println("method3");
	}
}

 

 

Client:

public class Client {
	public static void main(String[] args) {
		Template templateTest = new ConcreteTemplate();
		templateTest.template();
	}
}

 

 

在junit3.8的源码中:

 于是我们首先把 TestCase分成几个方法,哪些是抽象操作以便让开发人员去实现,哪个是Junit 中的设计模式,具体的模板方法,现在我们来看TestCase源码:

 

 

public abstract class TestCase extends Assert implements Test {
	//定义抽象操作,以便让子类实现
	protected void setUp() throws Exception {
	}
	protected void runTest() throws Throwable {
	}
	protected void tearDown() throws Exception {
	}
	//具体的模板方法,定义出逻辑骨架
	public void runBare() throws Throwable {
	setUp();
	runTest();
	tearDown();
	}
}

 setUp方法让测试人员实现,去初始化测试信息,如数据库的连接, EJB Home接口的JNDI等,而tearDown方法则是实现测试完成后的资源释放等清除操作。runTest方法则是开发人员实现的测试业务逻辑。最后TestCase的方法runBare则是模板方法,它实现了测试的逻辑骨架,而测试逻辑的组成步骤setUp, runTest, teardown,推迟到具体的子类实现,如一个具体的测试类:

public class TestHelloWorldTestClientJUnit1 extends TestCase {
	public void setUp() throws Exception {
		initialize();//初始化JNDI信息
		create(); //获得EJB的Home接口,和远程接口
	}
	public void testGetMessage() throws RemoteException {
		assertNotNull(ERROR_NULL_REMOTE, helloWorld);
		this.assertEquals("Hello World",helloWorld.getMessage(""));//测试业务逻辑
	}
	public void tearDown() throws Exception {
		helloWorldHome = null; //释放EJB的Home接口
		helloWorld = null; //释放EJB的远程接口
	}
}

 子类实现了setUp,tearDown方法,和一个测试方法testGetMessage,为什么名称不是runTest,这就是在下面介绍Adapter模式的原因,它把testGetMessage方法适配成runTest。

 

效果
我们来考虑经过使用Template Method模式后给系统的架构带来了那些效果:
1、 在各个测试用例中的公共的行为(初始化信息和释放资源等)被提取出来,可以避免代码的重复,简化了测试人员的工作。
2、在TestCase中实现一个算法的不变部分,并且将可变的行为留给子类来实现。增强了系统的灵活性。使JUnit框架仅负责算法的轮廓和骨架,而测试的开发人员则负责给出这个算法的各个逻辑步骤。

分享到:
评论

相关推荐

    Android开发三剑客_part2

    下篇对单元测试用例 测试的生命周期 自动化测试等均进行深入的分析与讲解 并结合模板方法模式 适配器模式 组合模式等深入解析JUnit框架的设计和实现思路 part2 总共2部分">从整体上来看 一款Android产品分为设计 ...

    Android开发三剑客_part1

    下篇对单元测试用例 测试的生命周期 自动化测试等均进行深入的分析与讲解 并结合模板方法模式 适配器模式 组合模式等深入解析JUnit框架的设计和实现思路 part1 总共2部分">从整体上来看 一款Android产品分为设计 ...

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    模板方法模式 访问者模式 设计案例 UML 架构 系统架构能力 基本理论 扩展性设计 可用性设计 可靠性设计 一致性设计 负载均衡设计 过载保护设计 协议设计 二进制协议 文本协议 接入层架构设计 DNS...

    design-patterns:带有单元测试的Java设计模式示例

    设计模式 带有单元测试的Java设计模式示例。 描述 该项目是一个个人库,其中包括一些重要的Java Design Patters,它们使用了漂亮有趣的示例并为每种模式实现了单元测试。 创作模式 单元测试 结构模式 单元测试 ...

    小区物业管理系统web项目,带Mysql数据库sql文件,带配置说明书,采用mvc设计模式,使用html,js,jsp等

    IDEA,是用于java语言开发的集成环境(也可用于其他语言),IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合、代码审查、 创新的GUI设计等...

    design-patterns-example-java:一个简单的设计模式示例,以Java Maven项目的形式

    设计模式示例Java Maven项目示例采用Junit 5的形式,但它们用作用法示例,而不是测试。内容(最有趣的去吧) 辛格尔顿战略工厂代理人适配器建造者MVC 状态观察者责任链装饰器模板合成的原型桥要旨这些示例的思想提供...

    重构-改善既有代码的设计 中文版.pdf

    10.12 Replace Co tructor with Factory Method(以工厂方法取代构造函数) 10.13 Encapsulate Downcast(封装「向下转型」动作) 10.14 Replace Error Code with Exception(以异常取代错误码) 10.15 Replace ...

    Spring攻略(第二版 中文高清版).part2

    13.1 用JUnit and TestNG创建测试 504 13.1.1 问题 504 13.1.2 解决方案 504 13.1.3 工作原理 504 13.2 创建单元测试和集成测试 509 13.2.1 问题 509 13.2.2 解决方案 509 13.2.3 工作原理 510 13.3...

    Spring攻略(第二版 中文高清版).part1

    13.1 用JUnit and TestNG创建测试 504 13.1.1 问题 504 13.1.2 解决方案 504 13.1.3 工作原理 504 13.2 创建单元测试和集成测试 509 13.2.1 问题 509 13.2.2 解决方案 509 13.2.3 工作原理 510 13.3...

    JAVA程序开发大全---上半部分

    8.1.1 MVC设计模式 117 8.1.2 Struts框架工作原理 118 8.1.3 Struts框架执行流程 118 8.2 MyEclipse创建基于Struts框架的项目 119 8.2.1 创建Struts项目 119 8.2.2 Struts组件向导 121 8.2.3 Struts配置文件编辑器 ...

    重构:改善既有代码的设计.[美]Martin Fowler.epub【文字版手机格式】

    本书也因此成为与《设计模式》齐名的经典著作,被译为中、德、俄、日等众多语言,在世界范围内畅销不衰。 本书凝聚了软件开发社区专家多年摸索而获得的宝贵经验,拥有不因时光流逝而磨灭的价值。今天,无论是重构...

Global site tag (gtag.js) - Google Analytics