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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值