JUnit是一個java語言的單元測試框架,是java測試裏最基本的框架。java
Android Studio建立的工程會自動集成JUnit,在build.gradle中添加相關依賴:git
testImplementation 'junit:junit:4.12'
複製代碼
測試框架的存在,並非必須的。它們只是爲了讓咱們寫更少的測試代碼。看下面示例,你會發現,所謂的單元測試方法,就像咱們初學java時,常寫的main方法。github
下面是使用JUnit進行測試的幾個例子。數據庫
//測試一個有返回值的方法
@Test
public void testMethod() {
int actual = Util.add(1, 2);
assertEquals(3, actual);
}
//測試一個沒有返回值,有反作用的方法
@Test
public void testMethodWithSideEffect() {
List<String> strings = Arrays.asList("a", "d", "b", "c");
List<String> excepted = Arrays.asList("a", "b", "c", "d");
//測試集合工具類的排序方法
Collections.sort(strings);
assertEquals(excepted, strings);
}
//測試一個方法拋異常的方案1
@Test
public void testMethodThrowException(){
Exception actual = null;
try {
Util.throwException();
}catch (Exception e){
actual = e;
}
assertEquals(IllegalArgumentException.class,actual.getClass());
}
//測試一個方法拋異常的方案2
@Test(expected = IllegalArgumentException.class)
public void testMethodThrowException2() {
Util.throwException();
}
複製代碼
如你所見,斷言是單元測試裏經常使用的東西。JUnit經常使用的斷言方法,都在org.junit.Assert類裏面,下面列出常見的幾個斷言方法。顧名思義,就很少說了。安全
assertEquals
assertNotEquals
assertArrayEquals
assertTrue
assertFalse
assertNull
assertNotNull
fail
...
複製代碼
相關內容主要來源於JUnit的源碼註釋,若有困惑,請參考源碼註釋。bash
用於標註public void
方法。被這個註解標記的方法,就是一個測試方法。一個測試類裏面,能夠有多個被@Test標註的測試方法。它們應該彼此獨立,互不影響。能夠點方法旁邊的綠色箭頭,單獨運行一個測試方法。app
也能夠點擊當前測試類旁邊的箭頭,執行測試類下面全部的測試方法。框架
還能夠一鍵運行test包下面的全部測試類。ide
注意:有兩種狀況會視爲測試失敗,不然測試成功。工具
1)測試方法拋異常。
2)你能夠這樣使用@Test(timeout = 100)
。設置超時時間,若是超時則視爲測試失敗。但這種作法是線程不安全的,因此官方推薦使用{@link org.junit.rules.Timeout} rule
來代替。
它們是方法級別的,用於標註public void
方法,會在被@Test標註的測試方法的一前一後運行,每調用一個測試方法都會執行一次,也就是@Before->@Test->@After。因此咱們一般會在被@Before標註的方法下作數據的初始化。在被@After標註的方法下,作數據的清除。
相似@Before和@After,但不一樣的是它們是類級別,也就是在執行一個測試類的時候只會調用一次,並且被它們標註的方法,必須是public static void
方法。這些方法只會運行一次,會被當前測試類裏面全部的測試方法共享。當測試都須要一些昂貴的操做的時候,就須要用到這兩個註解。雖然,這會讓測試的獨立性進行了必定的妥協,但有時這是一個有必要的優化操做。好比,數據庫的鏈接和關閉。
這是一個很是強大的註解。
@Rule是方法級別的,每一個測試方法執行時都會調用被標註的Rule。
能夠標註是public
但非靜態,且是TestRule子類的成員變量,如:
@Rule
public TemporaryFolder folder= new TemporaryFolder();
複製代碼
也能夠標註是public
但非靜態,並且必須返回一個TestRule子類的實例的方法,如:
private TemporaryFolder folder= new TemporaryFolder();
@Rule
public TemporaryFolder getFolder() {
return folder;
}
複製代碼
TestRule是一個接口類,能夠利用它,添加自定義的檢查,或者執行必要的設置或清理。TestRule能夠作@Before、@After、@BeforeClass和@AfterClass這幾個註解能作的全部事,但它每每更強大。
junit也爲咱們提供了幾個TestRule的具體實現,如Timeout、TemporaryFolder。下面給出一個使用示例:
public class Test {
//只須要用@Rule標註一個是TestRule子類的成員變量。
//這樣,若是該類中的任意測試方法超過5000ms任未完成,則該測試失敗。
@Rule
public Timeout timeout = new Timeout(5000);
//其他代碼略...
}
複製代碼
咱們也徹底能夠實現屬於本身的TestRule,將本身測試類裏面經常使用的設置或者清理等重複性高的代碼,封裝進去,簡化測試代碼。
public class YourRule implements TestRule {
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
//作一些預先的設置,或者任何你想作的事
//如數據庫表的建立
......
//這裏就是測試方法(包括了before、after在裏面)
//下面是官方源碼裏,對Statement接口的描述
//Represents one or more actions to be taken at runtime in the course
//of running a JUnit test suite.
base.evaluate();
//作一些清理,或者任何你想作的事
//如數據庫表的刪除
......
}
};
}
}
複製代碼
注:若是是對TestRule的具體實現仍然感到迷惑,也能夠參考官方給出的那幾個具體實現。
@ClassRule和@Rule類似,不一樣點是,@ClassRule是類級別的,只能用於標註靜態成員(成員變量,成員方法),在執行一個測試類的時候只會調用一次被註解的Rule。
被該註解標記的測試方法,會被忽略,不會被運行。
測試類的執行順序可經過對測試類添加註解 「@FixMethodOrder(value)」 。 三種執行順序可供選擇:
MethodSorters.DEFAULT:默認順序由方法名hashcode值來決定,若是hashcode值同樣,就使用MethodSorters.NAME_ASCENDING來排序。
MethodSorters.NAME_ASCENDING:按字符的字典順序,會始終保持一致。
MethodSorters.JVM:順序可能因運行而異,說白了就是不固定。
感受這是一個很雞肋註解。。
文中的相關測試例子,以及更多的測試例子都可以在UnitTest裏面找到。
若是你對一些知識點理解不透徹,也許參考更多的博客也未必有用。我建議,你應該去好好翻閱一下官方的源碼註釋。這或許能幫助你更深刻理解這些東西,畢竟不少博客的描述,就是源自源碼註釋。