JUnit源码分析 (三)——Template Method模式

简介:
在JUnit执行测试时,我们经常需要初始化一些环境供测试代码使用,比如数据库连接、mock对象等等,这些初始化代码应当在每一个测试之前执行并在测试方法运行后清理。在JUnit里面就是相应的setUp和tearDown方法。如果没有这两个方法,那么我们要在每个测试方法的代码内写上一大堆重复的初始化和清理代码,这是多么愚蠢的做法。那么JUnit是怎么让setUp和tearDown在测试执行前后被调用的呢?
    如果你查看下TestCase方法,你会发现TestCase和TestSuite的run()方法都是将执行测试的任务委托给了TestResult,由TestResult去执行测试代码并收集测试过程中的信息(这里用到了Collecting Parameter模式)。
   
    public  TestResult run() {
        TestResult result
=  createResult();
        run(result);
        
return  result;
    }
    
/**
     * Runs the test case and collects the results in TestResult.
     * This is the template method that defines the control flow
     * for running a test case.
     
*/
    
public   void  run(TestResult result) {
        result.run(
this );
    }
   
    我们直接找到TestResult,看看它的run方法:
/**
     * Runs a TestCase.
     
*/
    
protected   void  run( final  TestCase test) {
        startTest(test);
        Protectable p 
=   new  Protectable() {
            
public   void  protect()  throws  Throwable {
                test.runBare();
            }
        };
        runProtected(test, p);
        endTest(test);
    }

    这里实例化了一个内部类,内部类实现了 Protectable接口的 protect()方法,并执行传入的TestCase的runBare()方法,显然,真正的测试代码在TestCase的runBare()方法中,让我们来看下:


         // 将被子类实现
     protected   void  setUp()  throws  Throwable {
    }
    
// 同上,将被具体的TestCase实现
     protected   void  tearDown()  throws  Throwable {
    }
     /**
     * 模板方法
     * Runs the bare test sequence.
     * 
@exception  Throwable if any exception is thrown
     
*/
    
public   void  runBare()  throws  Throwable {
        setUp();
        
try  {
            runTest();
        }
        
finally  {
            tearDown();
        }
    }

真相水落石出,对于每一个测试方法,都遵循这样的模板:setUp->执行测试 runTest()->tearDown。这正是模板方式模式的一个应用例子。什么是template method模式呢?

Template Method模式

类行为模式的一种
1.意图:定义一个操作中的算法的骨架,而将一些延迟步骤到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。
2.适用场景:
1)一次性实现算法的不变部分(基本骨架),将可变的行为留给子类来完成
2)子类中的公共部分(比如JUnit中的初始化和清理)被抽取到一个公共父类中以避免代码重复。
3)控制了子类的扩展,这里其实也有类似回调函数的性质,具体步骤先在骨架中注册,在具体执行时被回调。

3.UML图和结构
    template.jpg
  抽象父类定义了算法的基本骨架(模板方法),而不同的子类实现具体的算法步骤,客户端由此可以与算法的更改隔离。

4.效果:
1)模板方法是代码复用的基本技术,在类库中经常使用,可以减少大量的代码重复
2)通过隔离算法的不变和可变部分,增加了系统的灵活性,扩展算法的某些步骤将变的很容易。

    了解了Template Method模式之后,让我们回到JUnit的源码,看看runTest()方法,这里主要应用的是java的反射技术,对于学习反射技术的有参考价值:
protected   void  runTest()  throws  Throwable {
        Method runMethod
=   null ;
        
try  {
            runMethod
=  getClass().getDeclaredMethod(fName,  new  Class[ 0 ]);
        } 
catch  (NoSuchMethodException e) {
            fail(
" Method \ "" +fName+ " \ "  not found " );
        }
        
if  (runMethod  !=   null   &&   ! Modifier.isPublic(runMethod.getModifiers())) {
            fail(
" Method \ "" +fName+ " \ "  should be public " );
        }

        
try  {
            runMethod.invoke(
this new  Class[ 0 ]);
        }
        
catch  (InvocationTargetException e) {
            e.fillInStackTrace();
            
throw  e.getTargetException();
        }
        
catch  (IllegalAccessException e) {
            e.fillInStackTrace();
            
throw  e;
        }
    }
文章转自庄周梦蝶  ,原文发布时间5.17
目录
相关文章
|
2月前
|
IDE Java 测试技术
Junit 单元测试
JUnit是Java常用的单元测试框架,简化了测试用例的编写和执行。其特点包括简单注解、自动化测试、可扩展性、灵活性及与IDE的集成。使用方法涉及创建测试类、利用注解如@Test、@BeforeEach等管理测试生命周期,以及使用各种断言方法验证结果。此外,JUnit支持参数化测试以覆盖更多输入组合,并能与Maven、Gradle等构建工具集成,提升测试效率和项目管理。
40 1
|
4月前
|
Java 测试技术
JUnit 4 单元测试
单元测试是软件开发中必不可少的一环,但是在平常开发中往往因为项目周期紧,工作量大而被选择忽略,这样往往导致软件问题层出不穷。 线上出现的不少问题其实在有单元测试的情况下就可以及时发现和处理,因此培养自己在日常开发中写单元测试的能力是很有必要的。无论是对自己的编码能力的提高,还是项目质量的提升,都是大有好处,本文将介绍 Java 单元测试框架 JUnit 4 的基础认识和使用来编写单元测试,希望同样对你有所帮助。
|
7月前
|
Java 测试技术 API
Junit5单元测试框架详解
前面我们学习了Selenium自动化测试框架,但是有的时候测试用例会很多,我们需要一个工具来管理这些测试用例,而Junit就是一个很好的管理工具,简单点来说,Junit就是一个针对Java的单元测试框架;
103 0
|
7月前
|
Java 测试技术 程序员
|
8月前
|
测试技术
Junit单元测试
Junit单元测试
37 0
|
8月前
|
Java 程序员 网络安全
JUnit5学习之六:参数化测试(Parameterized Tests)基础
了解JUnit5的参数化测试的基本知识
117 2
JUnit5学习之六:参数化测试(Parameterized Tests)基础
|
5月前
|
测试技术
Junit单元测试 org.junit.jupiter.api.extension.ParameterResolutionException异常处理
Junit单元测试 org.junit.jupiter.api.extension.ParameterResolutionException异常处理
90 0