• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 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

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>