JUnit源碼解析(2)

發表于:2016-10-04來源:saymagic作者:saymagic點擊數: 標簽:junit
} 可以看到,整個構造函數大致都在做一些驗證和初始化的工作,需要引起我們注意的應該是scanAnnotatedMembers方法: protected void scanAnnotatedMembers(MapClass? exte
}
可以看到,整個構造函數大致都在做一些驗證和初始化的工作,需要引起我們注意的應該是scanAnnotatedMembers方法:
 
 protected void scanAnnotatedMembers(Map<Class<? extends Annotation>, List<FrameworkMethod>> methodsForAnnotations, Map<Class<? extends Annotation>, List<FrameworkField>> fieldsForAnnotations) {
       for (Class<?> eachClass : getSuperClasses(clazz)) {
            for (Method eachMethod : MethodSorter.getDeclaredMethods(eachClass)) {
                addToAnnotationLists(new FrameworkMethod(eachMethod), methodsForAnnotations);
            }
            // ensuring fields are sorted to make sure that entries are inserted
            // and read from fieldForAnnotations in a deterministic order
            for (Field eachField : getSortedDeclaredFields(eachClass)) {
                addToAnnotationLists(new FrameworkField(eachField), fieldsForAnnotations);
            }
      }
}
整個函數的作用就是掃描class中方法和變量上的注解,并將其根據注解的類型進行分類,緩存在methodsForAnnotations與fieldsForAnnotations當中。需要注意的是,JUnit對方法和變量分別封裝為FrameworkMethod與FrameworkField,它們都繼承自FrameworkMember,這樣就為方法和變量進行了統一抽象。
 
看完了ParentRunner的構造函數,我們來看ParentRunner繼承自Runner的run方法是如何工作的:
 
@Override
public void run(final RunNotifier notifier) {
     EachTestNotifier testNotifier = new EachTestNotifier(notifier,
             getDescription());
     try {
         Statement statement = classBlock(notifier);
         statement.evaluate();
     } catch (AssumptionViolatedException e) {
         testNotifier.addFailedAssumption(e);
     } catch (StoppedByUserException e) {
         throw e;
     } catch (Throwable e) {
         testNotifier.addFailure(e);
     }
}
其中比較關鍵的代碼是classBlock函數將notifier轉換為Statement:
 
protected Statement classBlock(final RunNotifier notifier) {
     Statement statement = childrenInvoker(notifier);
     if (!areAllChildrenIgnored()) {
         statement = withBeforeClasses(statement);
         statement = withAfterClasses(statement);
         statement = withClassRules(statement);
     }
     return statement;
}
繼續追進childrenInvoker之前,允許我現在這里先存個檔,記為A,一會我們會回到classBlock這里
 
protected Statement childrenInvoker(final RunNotifier notifier) {
        return new Statement() {
            @Override
            public void evaluate() {
                runChildren(notifier);
            }
        };
    }
childrenInvoker返回的是一個Statement,看它的evaluate方法,其調用的是runChildren方法,這也是ParentRunner中非常重要的一個函數:
 
private void runChildren(final RunNotifier notifier) {
    final RunnerScheduler currentScheduler = scheduler;
    try {
         for (final T each : getFilteredChildren()) {
               currentScheduler.schedule(new Runnable() {
                    public void run() {
                        ParentRunner.this.runChild(each, notifier);

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

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