Junit使用及其原理分析
作者:
alighters 發(fā)布時間:
[ 2016/9/13 10:53:28 ] 推薦標(biāo)簽:
單元測試 Junit
其會調(diào)到一個 run(Runner runner) 的方法,而 Runner 是一個抽象類,其實現(xiàn)針對不同的平臺又有好多個。這里主要提及兩個,一個是 Junit4ClassRunner,它是 4.4 版本及之前的采用的,之后被廢棄掉了,而采用了繼承實現(xiàn)抽象類 ParentRunner 的 BlockJUnit4ClassRunner 類,它在 4.5 之后被采用。這里主要查看后者,先看 ParentRunner 對其接口 Runner 中方法 run 的實現(xiàn):
@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 方法生成的 Statement 的 evaluate來進(jìn)行調(diào)用,先看它是怎么生成的:
protected Statement classBlock(final RunNotifier notifier) {
Statement statement = childrenInvoker(notifier);
if (!areAllChildrenIgnored()) {
statement = withBeforeClasses(statement);
statement = withAfterClasses(statement);
statement = withClassRules(statement);
}
return statement;
}
這里主要的方法 childrenInvoker 會調(diào)用一個抽象的方法 protected abstract void runChild(T child, RunNotifier notifier);,它則是由子類來實現(xiàn)。另外看到的是,當(dāng)測試類中的測試方法都沒有被忽略的時候,則會使用 with對應(yīng)的三個方法來添加其獲取注解 BeforeClass,AfterClass,ClassRule對應(yīng)的信息,并添加至其調(diào)用的 statement中。
接下來查看 BlockJUnit4ClassRunner 的 runChild的實現(xiàn):
@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);
}
}
其中,若是添加了 @ignore的注解,則不會得到調(diào)用。看看 methodBlock方法都干了什么:
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;
}
在這個 statement 的獲取中,通過使用組合的方式,會這個 statement 添加 Before,After 及其它 Rule 的鏈?zhǔn)秸{(diào)用,后生成一個 statement 來返回。
總結(jié)
可以看出 Junit 是一個簡單而又強(qiáng)大的庫,不然不會經(jīng)久不衰。其簡單的實現(xiàn)但又強(qiáng)大的功能已經(jīng)基本滿足我們絕大多數(shù)的需求。但在這里還有一個疑問是不知道 Junit 是如何繼承到 Android Studio 的 IDE 中,并是如何直接調(diào)用我們的測試方法或者測試類的?