iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0
Software Development

關於我和 Spring Boot 變成家人的那件事系列 第 18

Day 18 - UnitTest (2) - Junit 5 測試方法與斷言應用

  • 分享至 

  • xImage
  •  

上一篇簡單說明基本測試的概念跟要怎麼建立測試程式在 Spring Boot 之後,這邊就來接著提供一些測試的設計原則和一些方法。

3A 原則 (3A Pattern)

  • Arrange: 初始化物件、要用到的參數
  • Act: 呼叫要測試的方法
  • Assert: 驗證測試結果

如果以上一篇的範例來看,我們要測試加法的功能會這樣設計就是應用到 3A 原則

  • Arrange:首先就是要先建立好測試的環境,把要用到的物件初始化,建立好相關的參數,也就是我們引入 Calculator 這個物件進入並且建立好要執行加法的參數。
  • Act:接著呼叫測試的方法並且帶入我們要的參數
  • Assert:利用斷言的方法來驗證,是否符合預期
class CalculatorTest {

    @Test
    void testAdd() {
		    // Arange
        Calculator calc = new Calculator();
        int x = 1;
        int y = 1;
        
        // Act
        int result = calc.add(x, y);
        
        // Assert
        assertEquals(2, result);
    }
}

常見斷言應用

斷言方法 說明
assertEquals(A, B) 預期 A 和實際 B 值相等,等同使用 equals() 方法比較,A和B 是基本類型
assertNotEquals(A, B) 預期 A 和實際 B 值不相等
assertTrue(A) A 條件判斷為 true
assertFalse(A) A 條件判斷為 false
assertNull(A) A 物件為空值
assertNotNull(A) A 物件不為空值
assertThrows(exception, method) 預期拋出 exception,method 為執行的方法,當執行該方法拋出對應的 exception 就會通過

如果接著我們打算擴充 Calculator 並且進行測試,多一個除法的功能,並且除以0會拋出 IllegalArgumentException

public int divide(int x, int y) {
        if (y == 0) {
            throw new IllegalArgumentException("不能除以 0");
        }
        return x / y;
    }

這邊就可以應用到那面那些方法,這邊也加入 message 可以協助我們沒通過出錯時會跳出對應的訊息,像是我這邊在 assertEquals, assertNotEquals 後面加入的訊息

@Test
    public void testDivide() {
        Calculator calc = new Calculator();
        int result = calc.divide(2,2);
        assertEquals(1, result, "result should be 1");
        assertNotEquals(0, result, "result should not be 0");
        assertTrue(result > 0);
        assertFalse(result != 1);
        assertThrows(IllegalArgumentException.class, () -> {
            calc.divide(2,0);
        });
    }

正常上面的 assert 都會通過。
如果 assertEquals 有出錯,假設我們把 1 改成 2 assertEquals(2, result, "result should be 1");
就可以看到 console 有把這段錯誤提示印出來
https://ithelp.ithome.com.tw/upload/images/20240927/20150977O6veBDLhQF.png

特別要說明就是 assertThrows() 這個方法需要放入第1個參數是 Exception.class,第2個用 lamda 表達式,把要執行驗證的方法加入到 ( )→{ } 的 { } 裡面。

大致上基本的設計原則還有 Junit 5 的斷言用法就介紹到這邊,下一篇會介紹進階使用 Mock 的部分。

補充 Intellij test coverage

這邊可以小補充一下 Intellij 有提供一個功能可以知道我們測試的覆蓋程度,這對於撰寫測試時式一個很好的指標參考,如果你的方法裡面有很多判斷或是條件,他會告訴你目前寫的測試大概涵蓋多少,如果把我們的剛剛寫的範例拿來測試。

在要執行的方法點選右鍵,可以看到用 Run test with Coverage
https://ithelp.ithome.com.tw/upload/images/20240927/20150977SzhUizxYoa.png

可以看到有顯示目前覆蓋的百分比,只有 50 %
https://ithelp.ithome.com.tw/upload/images/20240927/20150977wriwyLzW9W.png

可以直接點擊右方項目跳到被測試的區域,並且給予顏色標記哪些有被測試到。
這邊注意到因為我們點 testDivide 所以沒有執行到 testAdd,所以他也標記出 add 方法沒被測。
https://ithelp.ithome.com.tw/upload/images/20240927/201509779yM3PJCf5U.png

解開註解後,包含 Exception 的測試後,確實覆蓋率有提升
https://ithelp.ithome.com.tw/upload/images/20240927/20150977L8DWvbNT4L.png

剩下沒滿足是因為我們只有執行 testDivide ,如果點選整個 CalculatorTest 的測試就會達到 100%
https://ithelp.ithome.com.tw/upload/images/20240927/20150977BHV1PYkPLZ.png


Ref:

相關文章也會同步更新我的部落格,有興趣也可以在裡面找其他的技術分享跟資訊。


上一篇
Day 17 - UnitTest (1) - 基本介紹及建立測試程式
下一篇
Day 19 - UnitTest (3) - Junit 5 常用註解
系列文
關於我和 Spring Boot 變成家人的那件事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言