JUnit源碼解析(4)

發表于:2016-10-04來源:saymagic作者:saymagic點擊數: 標簽:junit
return befores.isEmpty() ? statement : new RunBefores(statement, befores, target); } 這個函數里首先拿到了所有被@Before標注的方法,將其封裝為RunBefores,我們看下其構造函數
        return befores.isEmpty() ? statement : new RunBefores(statement,
                befores, target);
}
這個函數里首先拿到了所有被@Before標注的方法,將其封裝為RunBefores,我們看下其構造函數和
 
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
        this.next = next;
        this.befores = befores;
        this.target = target;
}
public void evaluate() throws Throwable {
       for (FrameworkMethod before : befores) {
            before.invokeExplosively(target);
       }
       next.evaluate();
}
很是明了,evaluate執行時,首先將before方法全部invoke來執行,然后才調用原始statement的evaluate方法。其余幾個函數與此類似,感興趣可以繼續查看。
 
如此,我們就明白了runLeaf方法的第一個參數Statement的由來,接下來就看下這個runLeaf方法做了什么,runLeaf在ParentRunner中有默認的實現:
 
 protected final void runLeaf(Statement statement, Description description,
            RunNotifier notifier) {
        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
        eachNotifier.fireTestStarted();
        try {
            statement.evaluate();
        } catch (AssumptionViolatedException e) {
            eachNotifier.addFailedAssumption(e);
        } catch (Throwable e) {
            eachNotifier.addFailure(e);
        } finally {
            eachNotifier.fireTestFinished();
        }
}
非常簡單,直接執行了statement的evaluate方法,需要注意的是這里的statement實例不一定是什么了,有可能是RunBefores,也有可能是RunAfters,這就和被測試類中的注解有關了。
 
講到這里,還記得前面我們說過的存檔A嗎?我們回到存檔A:
 
protected Statement classBlock(final RunNotifier notifier) {
     Statement statement = childrenInvoker(notifier);
     if (!areAllChildrenIgnored()) {
         statement = withBeforeClasses(statement);
         statement = withAfterClasses(statement);
         statement = withClassRules(statement);
     }
     return statement;
}
剛剛存檔后所發生的一起,其實就是在執行Statement statement = childrenInvoker(notifier)這個代碼。換句話說,childrenInvoker的作用就是將所有需要執行的測試用例用一個Statement封裝起來。進而點燃這個Statement,就會觸發所有的測試用例。但同樣需要注意到被if語句包圍的代碼,我們又看到了熟悉的語句,Statement還在被不斷的轉換,但此時是在類的層面,withBeforeClasses函數操作的就是@BeforeClass注解了:
 
protected Statement withBeforeClasses(Statement statement) {
        List<FrameworkMethod> befores = testClass
                .getAnnotatedMethods(BeforeClass.class);
        return befores.isEmpty() ? statement :
                new RunBefores(statement, befores, null);
}
需要注意的是這回RunBefores的第三個參數為null,說明被@BeforeClass注解的方法只能是static的。
 
如上,我們分析了BlockJUnit4ClassRunner的運行流程,也就是說當測試類為一個的時候JUnit是如何工作的。前文也提到過,ParentRunner還有一個子類Suite,表示需要運行一組測試,BlockJUnit4ClassRunner的一個運行單元為FrameworkMethod,而Suite的一個運行單元為Runner,我們看其runChild方法:
 
protected void runChild(Runner runner, final RunNotifier notifier) {

原文轉自:http://blog.saymagic.cn/2016/09/30/understand-Junit.html

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97