【高效編碼】超全面的,超正的單元測試框架Junit的使用姿勢

文章目錄

    單元測試有啥用?
        Junit4的簡介
        Junit的使用
        相關(guān)注解的說明
        斷言
    擴展延伸
    總結(jié)
    參考

單元測試有啥用?

學(xué)習(xí)一個技術(shù)或者一個框架,我們首先會考慮的一個問題這個框架有啥用,能解決什么問題?只有能提升生產(chǎn)力的工具才是好工具。針對這個問題,想想下面這個場景,在不用單元測試的情況下,當(dāng)你編寫了一個很復(fù)雜的方法后,該如何測試該方法的是不是有bug。除了代碼review和編寫一個main方法手動調(diào)用該方法,是不是沒有其他更好的方法,如果有的話,歡迎讀者朋友們積極留言,讓我學(xué)習(xí)一下。。很明顯上面說的兩種方法各有各的弊端,首先是代碼review這種方式,光看不調(diào),對于一些隱藏很深的bug還是比較難發(fā)現(xiàn)。然后就是編寫一個main方法調(diào)用,如果方法很多的話,都用一個main方法來調(diào)用的話,main方法會非常的龐大,還可能會出現(xiàn)方法之間相互影響的情況。綜上所述,就要請出我們的單元測試框架了。讓單元測試來大顯身手。
Junit4的簡介

Junit框架是一種應(yīng)用非常廣泛的單元測試框架。使用也是非常的方便。其在單元測試領(lǐng)域有著廣泛的應(yīng)用,主要分為Junit4和Junit5兩個主要的版本。其中Junit 及其之前的版本是將所有內(nèi)容放到一個jar中,JUnit 5 由三個不同的模塊組成。包括JUnit 平臺、 JUnit Jupiter、 JUnit Vintage。Junit有如下幾個特點:

獨立于業(yè)務(wù)代碼之外對業(yè)務(wù)代碼進行測試,這樣的好處就是可以不影響業(yè)務(wù)代碼。
在打包的時候可以將單元測試的代碼踢出。
修改業(yè)務(wù)代碼之后可以執(zhí)行單元測試代碼,看看功能有沒有bug。
下面以Junit 4為例進行說明。

Junit的使用

說了一堆Junit的介紹和好處,那么Junit該如何使用呢?先舉個簡單的栗子。下面定義了一個待測試的業(yè)務(wù)類Calculate類,它有加減乘除四個方法。

public class Calculate {

public int add(int a, int b) {
    return a + b;
}

public int substract(int a, int b) {
    return a - b;
}

public int multiply(int a, int b) {
    return a * b;
}

public int division(int a, int b) {
    return a / b;
}

}

現(xiàn)在要對這個類里的每個方法進行單元測試,第一步還是要引入junit依賴(在此默認(rèn)你的項目是通過maven管理的)。


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

在Idea中按下Ctrl+Shift+T快捷鍵就可以創(chuàng)建一個單元測試類。下面就展示這個測試類。

@RunWith(JUnit4.class)
public class CalculateTest {
private static Calculate calculate;

private static int A = 4;
private static int B = 0;

@BeforeClass
public static void initClass() {
    System.out.println("針對所有測試,只運行一次");
    calculate = new Calculate();
}

@Before
public void setUp() {
    System.out.println("測試方法運行前執(zhí)行");
}

@Test
public void add() {
    int add = calculate.add(1, 2);
    Assert.assertEquals(3, add);
    System.out.println("對add單元測試完成");
}

@Test
public void substract() {
    int substract = calculate.substract(A, B);
    Assert.assertEquals(4, substract);
    System.out.println("對substract單元測試完成");
}

@Test
public void multiply() {
    int multiply = calculate.multiply(A, B);
    Assert.assertEquals(0, multiply);
    System.out.println("對multiply單元測試完成");
}

@Test
public void division() {
    //正常情況
    int division = calculate.division(A, 1);
    Assert.assertEquals(4, division);
    System.out.println("對division單元測試完成");
}

@Test(expected = ArithmeticException.class)
public void division2() {
    int division = calculate.division(A, B);
    System.out.println("對異常情況單元測試完成");
}

}

單元測試運行結(jié)果:

相關(guān)注解的說明

單元測試的執(zhí)行主要是通過相關(guān)注解來驅(qū)動的。所以,了解各個注解的作用顯的尤為重要。

@RunWith這個注解修飾的是測試類,作用在類上表示該測試類所使用的測試驅(qū)動。
@Test :這個注解表明被修飾的方法是測試方法,在Junit中將會被自動執(zhí)行,需要注意的是,測試方法只能是無返回值無參數(shù)的公共方法,即public void 。方法名可以任意?。ńㄗh是跟被測試方法同名),方法不能有入?yún)ⅰ.?dāng)然@Test 注解內(nèi)還能傳入一些參數(shù),例如:本例中@Test(expected = ArithmeticException.class) 就是預(yù)期被測試的方法會拋出ArithmeticException異常,可以理解異常捕獲。還可以傳入超時時間,比如 @Test(timeout = 100):我們給測試函數(shù)設(shè)定一個執(zhí)行時間,超過了這個時間(100毫秒),它們就會被系統(tǒng)強行終止,并且系統(tǒng)還會向你匯報該函數(shù)結(jié)束的原因是因為超時,這樣你就可以發(fā)現(xiàn)這些Bug了。
@BeforeClass 這個注解針對所有測試,在所有測試方法執(zhí)行之前執(zhí)行,且只執(zhí)行一次,且必須是作用在public static void,即修飾靜態(tài)方法,知道原因的小伙伴歡迎留言回答。
@AfterClass 這個注解針對所有的測試,將會在所有測試方法執(zhí)行結(jié)束后執(zhí)行一次,且必須作用到public static void。
@Before 初始化方法,每個測試方法運行之前必須執(zhí)行被@Before注解修飾的方法。
@After 釋放資源,在任何測試方法執(zhí)行之后需要進行的收尾工作,在每個測試方案執(zhí)行之后執(zhí)行一次,該注解作用到public static void。
@Ignore 忽略的測試方法,標(biāo)注的含義就是"某些方法尚未完成,暫不參與此次測試",被@Ignore注解修飾的方法不會被執(zhí)行。
在這里插入圖片描述

斷言

一個完整的單元測試有三個步驟:

準(zhǔn)備(測試環(huán)境,準(zhǔn)備測試數(shù)據(jù))
執(zhí)行(構(gòu)造請求傳入?yún)?shù)執(zhí)行)
斷言(驗證結(jié)果)
前面介紹完了準(zhǔn)備和執(zhí)行兩個步驟,下面就是介紹斷言這個步驟了,Junit測試框架中Assert類就是實現(xiàn)斷言的工具,它主要作用如下:1. 單元測試用于判斷某個特定條件下某個方法的行為;執(zhí)行單元測試為了證明某段代碼的執(zhí)行結(jié)果和期望的一致。總而言之,斷言的作用就白了就是驗證被測試方法的返回結(jié)果。
Assert類中用于斷言的方法有很多,下面介紹幾個常用的斷言方法。
assertEquals(expected, actual):查看兩個對象或者兩個值是否相等,如果是對象的話就是使用equal()方法來比較。參數(shù)expected為用戶期望的值,actual為被測試方法實際返回的值。如果這兩個值相等的話, 則說明方法運行是正確的。
assertNull()查看對象是否為空。
assertSame(expected,actual):查看兩個對象的引用是否相等,直接用==來進行比較的。比較兩個對象的值是否相等。
assertTrue(String message, boolean condition) 要求condition==true,查看運行的結(jié)果是否為true。

擴展延伸

上面介紹的都是一些基本的概念,實在是不過癮,只能算一個demo級別的知識點。那我一個用Spring容器管理的類如何測試測試呢?我圖片上傳的方法如何測試呢?這些都沒講嘛,沒意思?。。?!哈哈哈,讀者朋友們,不要著急,項目級別的實戰(zhàn)在后面呢!
SpringBoot項目的單元測試請看這篇文章一分鐘上手SpringBootTest
SpringMVC項目的單元測試請看這篇文章 SpringMVC框架如何與Junit整合,看這個就夠了
總結(jié)

本文是一個Junit4框架使用的基礎(chǔ)篇,詳細(xì)介紹了Junit4框架的使用,以及Junit框架中各種注解的作用。希望對讀者朋友們有所幫助。





作者:碼農(nóng)飛哥
微信公眾號:碼農(nóng)飛哥