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