Java單元測試和Mock

隨筆 2019年8月26日

單元測試

什么是單元測試

單元測試是對軟件或程序的基本(最?。┙M成。

特點:

  • 可重復執(zhí)行
  • 執(zhí)行速度快
  • 獨立無依賴
  • 結(jié)果不改變

為什么要寫單元測試

  • 使我們更了解需求
  • 快速驗證
  • 使重構(gòu)更容易
  • 更早了解程序的問題

Junit

例子

import org.junit.*;
import static org.junit.Assert.fail;

public class ClassNameTest {
    @BeforeClass    //公開表態(tài)無返回值
    public static void beforeClass() throws Exception{
        //每次測試類執(zhí)行前執(zhí)行一次,主要用來初使化公共資源等
    }
    @AfterClass     //公開表態(tài)無返回值
    public static void afterClass() throws Exception{
        //每次測試類執(zhí)行完成后執(zhí)行一次,主要用來釋放資源或清理工作
    }
    @Before
    public void setup() throws Exception {
        //每個測試案例執(zhí)行前都會執(zhí)行一次
    }
    @After
    public void teardown() throws Exception {
        //每個測試案例執(zhí)行完成后都會執(zhí)行一次
    }
    @Test
    public void testMethodName_give_…_when_…_then_…() {
        fail("失敗");
    }
}

常用的注解

  • @Ignore

    該注解標記的測試方法在測試中會被忽略。

  • @Test

    @Test(expected=xxxException.class) 斷言該方法會拋出異常
    @Test(timeout=1000) 執(zhí)行時間超過設(shè)置的值該案例會失敗

  • @RunWith

    @RunWith(Suite.class) 測試集運行器配合使用測試集功能
    @RunWith(JUnit4.class) 默認運行器
    @RunWith(Parameterized.class) 參數(shù)化運行器

  • @Before

    初始化方法,在任何一個測試方法執(zhí)行之前,必須執(zhí)行的代碼。對比 JUnit 3 ,和 setUp()方法具有相同的功能。在該注解的方法中,可以進行一些準備工作,比如初始化對象,打開網(wǎng)絡(luò)連接等。

  • @After

    釋放資源,在任何一個測試方法執(zhí)行之后,需要進行的收尾工作。對比 JUnit 3 ,和 tearDown()方法具有相同的功能。

  • @BeforeClass

    針對所有測試,也就是整個測試類中,在所有測試方法執(zhí)行前,都會先執(zhí)行由它注解的方法,而且只執(zhí)行一次。當然,需要注意的是,修飾符必須是 public static void xxxx ;此 Annotation 是 JUnit 4 新增的功能。

  • @AfterClass

    針對所有測試,也就是整個測試類中,在所有測試方法都執(zhí)行完之后,才會執(zhí)行由它注解的方法,而且只執(zhí)行一次。當然,需要注意的是,修飾符也必須是 public static void xxxx ;此 Annotation 也是 JUnit 4 新增的功能,與 @BeforeClass 是一對。

斷言

常用的斷言方法如下:

  • assertEquals(a, b)
    測試a是否等于b(a和b是原始類型數(shù)值(primitive value)或者必須為實現(xiàn)比較而具有equal方法)

  • assertFalse(a)
    測試a是否為false(假),a是一個Boolean數(shù)值。

  • assertTrue(a)
    測試a是否為true(真),a是一個Boolean數(shù)值

  • assertNotNull(a)
    測試a是否非空,a是一個對象或者null。

  • assertNull(a)
    測試a是否為null,a是一個對象或者null。

  • assertNotSame(a, b)
    測試a和b是否沒有都引用同一個對象。

  • assertSame(a, b)
    測試a和b是否都引用同一個對象。

  • fail(string)
    Fail讓測試失敗,并給出指定信息。

  • assertThat(expected, Matcher)
    通過Matcher斷言

執(zhí)行順序

在 JUnit 4 中,單元測試用例的執(zhí)行順序為:

@Before → @Before → @Test → @After → @AfterClass

建議

要寫注釋,建議分為如下4步驟。

  1. 測試場景
  2. 準備數(shù)據(jù)
  3. 測試執(zhí)行
  4. 斷言

Mock

前言

為什么需要Mock或Stub?它與Junit什么關(guān)系?

在做單元測試的時候,我們會發(fā)現(xiàn)我們要測試的方法會引用很多外部依賴的對象。 而我們沒法控制這些外部依賴的對象。為了解決這個問題,我們需要用到Stub和Mock來模擬這些外部依賴的對象,從而控制它們。

JUnit是單元測試框架,可以輕松的完成關(guān)聯(lián)依賴關(guān)系少或者比較簡單的類的單元測試,但是對于關(guān)聯(lián)到其它比較復雜的類或?qū)\行環(huán)境有要求的類的單元測試,模擬環(huán)境或者配置環(huán)境會非常耗時,實施單元測試比較困難。而這些Mock框架(Mockito 、jmock 、 powermock、EasyMock),可以通過mock框架模擬一個對象的行為,從而隔離開我們不關(guān)心的其他對象,使得測試變得簡單。

例如: service調(diào)用dao,即service依賴dao,我們可以通過mock dao來模擬真實的dao調(diào)用,從而能達到測試service的目的。

模擬對象(Mock Object)可以取代真實對象的位置,用于測試一些與真實對象進行交互或依賴于真實對象的功能,模擬對象的背后目的就是創(chuàng)建一個輕量級的、可控制的對象來代替測試中需要的真實對象,模擬真實對象的行為和功能。

Mock與Stub什么區(qū)別?

Mock和Stub是兩種測試代碼功能的方法。Mock測重于對功能的模擬,Stub測重于對功能的測試重現(xiàn)。比如對于List接口,Mock會直接對List進行模擬,而Stub會新建一個實現(xiàn)了List的TestList,在其中編寫測試的代碼。
強烈建議優(yōu)先選擇Mock方式,因為Mock方式下,模擬代碼與測試代碼放在一起,易讀性好,而且擴展性、靈活性都比Stub好。

其中EasyMock和Mockito對于Java接口使用接口代理的方式來模擬,對于Java類使用繼承的方式來模擬(也即會創(chuàng)建一個新的Class類)。Mockito支持spy方式,可以對實例進行模擬。但它們都不能對靜態(tài)方法和final類進行模擬,powermock通過修改字節(jié)碼來支持了此功能。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容