JUnit源碼解析(3)

發表于:2016-10-04來源:saymagic作者:saymagic點擊數: 標簽:junit
} }); } } finally { currentScheduler.finished(); } } 這個函數就體現了抽象的重要性,注意泛型T,它在ParentRunner的每個實現類中各不相同,在BlockJUnit4ClassRunner中T表示
                    }
               });
         }
     } finally {
         currentScheduler.finished();
     }
}
這個函數就體現了抽象的重要性,注意泛型T,它在ParentRunner的每個實現類中各不相同,在BlockJUnit4ClassRunner中T表示FrameworkMethod,具體到這個函數來講getFilteredChildren拿到的是被@Test注解標注的FrameworkMethod,而在Suite中,T為Runner,而ParentRunner.this.runChild(each, notifier);這句的中的runChild(each, notifier)方法依舊是個抽象方法,我們先看BlockJUnit4ClassRunner中的實現:
 
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
     Description description = describeChild(method);
     if (isIgnored(method)) {
         notifier.fireTestIgnored(description);
     } else {
         runLeaf(methodBlock(method), description, notifier);
     }
}
isIgnored方法判斷了method方法是否被@Ignore注解標識,如果是的話則直接通知notifier觸發ignored事件,否則,執行runLeaf方法, runLeaf的第一個參數是Statement,所以,BlockJUnit4ClassRunner通過methodBlock方法將method轉換為Statement:
 
protected Statement methodBlock(FrameworkMethod method) {
        Object test;
        try {
            test = new ReflectiveCallable() {
                @Override
                protected Object runReflectiveCall() throws Throwable {
                    return createTest();
                }
            }.run();
        } catch (Throwable e) {
            return new Fail(e);
        }
        Statement statement = methodInvoker(method, test);
        statement = possiblyExpectingExceptions(method, test, statement);
        statement = withPotentialTimeout(method, test, statement);
        statement = withBefores(method, test, statement);
        statement = withAfters(method, test, statement);
        statement = withRules(method, test, statement);
        return statement;
 }
前面的幾行代碼是在生成test 對象,而test對象的類型則是我們待測試的class,接下來追進methodInvoker方法:
 
protected Statement methodInvoker(FrameworkMethod method, Object test) {
        return new InvokeMethod(method, test);
}
可見,我們生成的Statement實例為InvokeMethod,我們看下其evaluate方法:
 
testMethod.invokeExplosively(target);
invokeExplosively函數做的事情就是對target對象調用testMethod方法。而前面我們說過,這個testMethod在BlockJUnit4ClassRunner中就是被@Test所標注的方法,此時,我們終于找到了@Test方法是在哪里被調用的了。別急,我們接著剛才的函數繼續分析:
 
statement = possiblyExpectingExceptions(method, test, statement);
statement = withPotentialTimeout(method, test, statement);
statement = withBefores(method, test, statement);
statement = withAfters(method, test, statement);
statement = withRules(method, test, statement);
我們可以看到,statement不斷的在變形,而通過withBefores,withRules這些函數的名字我們可以很容易猜到,這里就是在處理@Before,@Rule等注解的地方,我們以withBefores為例:
 
protected Statement withBefores(FrameworkMethod method, Object target,
            Statement statement) {
        List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
                Before.class);

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

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