[转]JUnit源码分析--Template Method模式

系统 1694 0

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

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

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


<!---->   
java 代码
  1.    //将被子类实现   
  2. protected   void  setUp()  throws  Throwable {   
  3. }   
  4. //同上,将被具体的TestCase实现   
  5. protected   void  tearDown()  throws  Throwable {   
  6. }   
  7.   /**  
  8.  * 模板方法  
  9.  * Runs the bare test sequence.  
  10.  * @exception Throwable if any exception is thrown  
  11.  */   
  12. public   void  runBare()  throws  Throwable {   
  13.     setUp();   
  14.      try  {   
  15.         runTest();   
  16.     }   
  17.      finally  {   
  18.         tearDown();   
  19.     }   
  20. }   
真相水落石出, 对于每一个测试方法,都遵循这样的模板:setUp->执行测试 runTest()->tearDown。这正是模板方式模式的一个应用例子 。什么是template method模式呢?

Template Method模式

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

3.UML图和结构
    [转]JUnit源码分析--Template Method模式
  抽象父类定义了算法的基本骨架(模板方法),而不同的子类实现具体的算法步骤,客户端由此可以与算法的更改隔离。

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

    了解了Template Method模式之后,让我们回到JUnit的源码,看看runTest()方法,这里主要应用的是java的反射技术,对于学习反射技术的有参考价值:
<!---->
java 代码
  1. protected   void  runTest()  throws  Throwable {   
  2.         Method runMethod=  null ;   
  3.          try  {   
  4.             runMethod= getClass().getDeclaredMethod(fName,  new  Class[ 0 ]);   
  5.         }  catch  (NoSuchMethodException e) {   
  6.             fail( "Method \"" +fName+ "\" not found" );   
  7.         }   
  8.          if  (runMethod !=  null  && !Modifier.isPublic(runMethod.getModifiers())) {   
  9.             fail( "Method \"" +fName+ "\" should be public" );   
  10.         }   
  11.   
  12.          try  {   
  13.             runMethod.invoke( this new  Class[ 0 ]);   
  14.         }   
  15.          catch  (InvocationTargetException e) {   
  16.             e.fillInStackTrace();   
  17.              throw  e.getTargetException();   
  18.         }   
  19.          catch  (IllegalAccessException e) {   
  20.             e.fillInStackTrace();   
  21.              throw  e;   
  22.         }   
  23.     }  

[转]JUnit源码分析--Template Method模式


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论