在实际的测试中,为了测试业务逻辑,必须构造一些参数或者一些资源,然后才可进行测试,最后必须释放这些系统资源。如测试数据库应用时,必须创建数据库连接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框架仅负责算法的轮廓和骨架,而测试的开发人员则负责给出这个算法的各个逻辑步骤。
分享到:
相关推荐
《Junit设计模式分析》这本书深入探讨了如何在单元测试框架Junit中巧妙地应用设计模式,以提高代码的可测试性和可维护性。在软件开发过程中,设计模式是解决常见问题的最佳实践,它们能够帮助开发者创建灵活、可扩展...
本篇将深入分析JUnit源码中的设计模式,帮助你理解其内在的架构原理,提升你的编程技能。 首先,JUnit的核心设计原则之一是“开闭原则”(Open-Closed Principle),它主张软件实体(类、模块、函数等)应对于扩展...
本资源"Junit设计模式分析(带源码)"旨在深入探讨JUnit在设计上的模式和最佳实践,通过源码分析帮助开发者更好地理解和应用这个工具。 1. 单元测试基础: 单元测试是对软件中的最小可测试单元进行检查,如函数、...
《JUnit设计模式分析》 JUnit是Java编程语言中广泛使用的单元测试框架,它极大地简化了对代码进行测试的过程。设计模式则是软件工程中的一种最佳实践,通过总结和抽象出常见问题的解决方案,使得开发者能够更好地...
设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板,可以被重复使用。在JUnit中,设计模式的应用提升了其灵活性和可扩展性。以下是一些在JUnit中常见的设计模式: 1. 工厂模式:JUnit通过...
本文将深入探讨JUnit中的设计模式,以及如何通过理解这些模式来简化JUnit的使用。 首先,JUnit的核心设计理念之一是“依赖注入”,这是设计模式中的一个关键概念。依赖注入允许测试类动态地获取它们所依赖的对象,...
这个框架的设计基于一系列高效的设计模式,这些模式不仅提升了JUnit的灵活性,还使得开发者能够方便地扩展和定制测试功能。 首先,JUnit的核心设计理念是“简单易用”。它遵循了“最小化API”原则,提供了一套简洁...
《Junit设计模式应用》是基于作者业余时间的翻译成果,旨在通过设计模式的角度深入剖析JUnit的内在原理,以此促进读者对单元测试框架理解和运用能力的提升。设计模式是软件工程中的宝贵经验总结,它为解决常见问题...
#### 二、JUnit中的设计模式概述 ##### 1. Command 模式 在JUnit中,`TestCase`类扮演了命令角色,即一个具体的命令对象。这种模式允许程序员将“请求”封装成对象,从而使程序员可以用不同的请求对客户进行参数化...
Java设计模式之模板方法模式Java认证考试 Java设计模式之模板方法模式是Java认证考试中的一种重要的设计模式,它通过使用继承关系来定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个...
在软件开发过程中,设计模式是解决常见问题的模板,它为特定场景提供了可重用的解决方案。JUNIT作为Java编程语言中最广泛使用的单元测试框架,能够帮助开发者验证代码的正确性和设计模式的有效应用。本篇将详细介绍...
模板模式是一种行为设计模式,它在Java编程中广泛应用于创建可扩展和可复用的代码。根据GoF的《设计模式》定义,模板方法模式是在一个操作中定义一个算法的骨架,将一些步骤延迟到子类中实现,使得子类可以在不改变...
设计模式是软件设计高手们经验的结晶,它们是经过验证的解决方案模板,可以帮助开发者高效地解决常见问题。 本书的目标包括理解和掌握面向对象设计的基本原则,了解设计模式的概念和常见模式,理解框架的概念和设计...
在"junit-4.8.2.jar"这个版本中,我们可以深入研究其设计模式的应用以及它如何支持测试驱动开发(TDD)的工作流程。 首先,JUnit 4.8.2引入了注解(Annotations)的概念,这是Java 5引入的一项特性。例如,`@Test`...
这种设计模式提供了更大的灵活性,并支持更为丰富的测试场景。 - **JUnit Platform**:这是整个JUnit5的基础,负责管理测试引擎和执行测试。 - **JUnit Jupiter**:提供了新的编程模型和API,用于编写和执行基于...
在软件工程领域,设计模式是一套被广泛接受的解决特定问题的解决方案模板。设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。 **1. 常见的设计模式有哪些?** - **单例模式(Singleton)**:确保一个...
Gamma是《设计模式:可复用面向对象软件的基础》一书的作者之一,而Beck则是极限编程(XP)的倡导者。JUnit以其简洁而强大的特性,极大地推动了单元测试在Java社区中的普及。 在开始使用JUnit 4之前,确保你已安装...