JUnit源碼解析(5)
發表于:2016-10-04來源:saymagic作者:saymagic點擊數:
標簽:junit
runner.run(notifier); } 很是明了,直接滴啊用runner的run方法。這樣,如果這個runner的實例仍然是Suite,則會繼續向里運行,如果這個runner為BlockJUnit4ClassRunner,這
runner.run(notifier);
}
很是明了,直接滴啊用runner的run方法。這樣,如果這個runner的實例仍然是Suite,則會繼續向里運行,如果這個runner為BlockJUnit4ClassRunner,這執行我們前面分析的邏輯。這里有個問題是,那這個runner是如何生成的呢?這就要看Suite的構造函數:
protected Suite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError {
this(new AllDefaultPossibilitiesBuilder(true), klass, suiteClasses);
}
AllDefaultPossibilitiesBuilder的職責就是為每個類生找到對應的Runner,感興趣可以查看其runnerForClass方法,比較容易理解,這里就不再贅述。
Matcher驗證
上面我們分析了用@Test標注的函數是如何被JUnit執行的,但單單有@Test標注是肯定不夠的,既然是測試,我們肯定需要一定的手段來驗證程序的的執行是符合預期的。JUnit提供了Matcher機制,可以滿足我們大部分的
需求。Matcher相關類主要在org.hamcrest包下,先來看下類圖:
上圖僅僅列出了org.hamcrest包下的一部分類,這些類一起組合起來形成了JUnit強大的驗證機制。
驗證的基本寫法是:
MatcherAssert.assertThat("saymagic", CoreMatchers.containsString("magic"));
首先我們需要調用的是MatcherAssert的assertThat方法,這個方法最終輾轉為:
public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) {
if (!matcher.matches(actual)) {
Description description = new StringDescription();
description.appendText(reason)
.appendText("\nExpected: ")
.appendDescriptionOf(matcher)
.appendText("\n but: ");
matcher.describeMismatch(actual, description);
throw new AssertionError(description.toString());
}
}
這個函數目的很是明確,直接判斷matcher是否匹配,不匹配則封裝描述信息,然后拋出異常。所以我們來關注matcher的matchs方法都做了些什么,CoreMatchers.containsString("magic")返回的就是一個matcher, CoreMatchers相當于一個靜態工廠,提供了大量的靜態方法來返回各種Matcher:
我們就已剛剛的containsString為例,查看其內部代碼:
public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
return org.hamcrest.core.StringContains.containsString(substring);
}
可見其調用了StringContains的一個靜態方法,繼續追:
@Factory
public static Matcher<String> containsString(String substring) {
return new StringContains(substring);
}
這里很簡單,直接new了一個StringContains實例,StringContains的繼承關系如下:
首先BaseMatcher實現了Matcher接口,TypeSafeMatcher是BaseMatcher的一個抽象實現,它的matches方法如下:
public final boolean matches(Object item) {
return item != null
&& expectedType.isInstance(item)
&& matchesSafely((T) item);
}
可見它在驗證前作了判空與類型的校驗,所以子類就可以實現matchesSafely方法,就無需在此方法中進行判空與類型的驗證了。
SubstringMatchers是TypeSafeMatcher的一種實現,它是對字符串類驗證的一種抽象,它的matchesSafely方法如下:
@Override
public boolean matchesSafely(String item) {