JUnit5學習之二:Assumptions類

程式設計師欣宸發表於2021-02-20

歡迎訪問我的GitHub

https://github.com/zq2599/blog_demos

內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;

關於《JUnit5學習》系列

《JUnit5學習》系列旨在通過實戰提升SpringBoot環境下的單元測試技能,一共八篇文章,連結如下:

  1. 基本操作
  2. Assumptions類
  3. Assertions類
  4. 按條件執行
  5. 標籤(Tag)和自定義註解
  6. 引數化測試(Parameterized Tests)基礎
  7. 引數化測試(Parameterized Tests)進階
  8. 綜合進階(終篇)

本篇概覽

本文是《JUnit5學習》系列的第二篇,學習一個重要的知識點:Assumptions類,只有瞭解了它們,才好繼續後面的學習,全篇章節如下:

  1. Assertions和Assumptions簡介
  2. 寫一段程式碼對比效果
  3. Assumptions編碼
  4. 檢視執行結果

原始碼下載

  1. 如果您不想編碼,可以在GitHub下載所有原始碼,地址和連結資訊如下表所示:
名稱 連結 備註
專案主頁 https://github.com/zq2599/blog_demos 該專案在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該專案原始碼的倉庫地址,https協議
git倉庫地址(ssh) git@github.com:zq2599/blog_demos.git 該專案原始碼的倉庫地址,ssh協議
  1. 這個git專案中有多個資料夾,本章的應用在junitpractice資料夾下,如下圖紅框所示:

在這裡插入圖片描述

  1. junitpractice是父子結構的工程,本篇的程式碼在assertassume子工程中,如下圖:

在這裡插入圖片描述

Assertions和Assumptions簡介

Assumptions和Assertions容易混淆,因此這裡通過對比它們來學習:

  1. Assertions即斷言類,裡面提供了很多靜態方法,例如assertTrue,如果assertTrue的入參為false,就會丟擲AssertionFailedError異常,Junit對丟擲此異常的方法判定為失敗;
  2. Assumptions即假設類,裡面提供了很多靜態方法,例如assumeTrue,如果assumeTrue的入參為false,就會丟擲TestAbortedException異常,Junit對丟擲此異常的方法判定為跳過;
  3. 簡單的說,Assertions的方法丟擲異常意味著測試不通過,Assumptions的方法丟擲異常意味著測試被跳過(為什麼稱為"跳過"?因為mvn test的執行結果被標記為Skipped);

寫一段程式碼對比效果

  1. 用程式碼來驗證的效果最好,如下所示,一共四個方法,assertSuccess不丟擲AssertionFailedError異常,assertFail丟擲AssertionFailedError異常,assumpSuccess不丟擲TestAbortedException異常,assumpFail丟擲TestAbortedException異常
package com.bolingcavalry.assertassume.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

@SpringBootTest
@Slf4j
public class AssertAssumpTest {

    /**
     * 最簡單的成功用例
     */
    @Test
    void assertSuccess() {
        assertEquals(2, Math.addExact(1,1));
    }

    /**
     * 最簡單的失敗用例
     */
    @Test
    void assertFail() {
        assertEquals(3, Math.addExact(1,1));
    }

    /**
     * assumeTrue不丟擲異常的用例
     */
    @Test
    void assumpSuccess() {
        // assumeTrue方法的入參如果為true,就不會丟擲異常,後面的程式碼才會繼續執行
        assumeTrue(true);
        // 如果列印出此日誌,證明assumeTrue方法沒有丟擲異常
        log.info("assumpSuccess的assumeTrue執行完成");
        // 接下來是常規的單元測試邏輯
        assertEquals(2, Math.addExact(1,1));
    }

    /**
     * assumeTrue丟擲異常的用例
     */
    @Test
    void assumpFail() {
        // assumeTrue方法的入參如果為false,就會丟擲TestAbortedException異常,後面就不會執行了
        assumeTrue(false, "未通過assumeTrue");
        // 如果列印出此日誌,證明assumpFail方法沒有丟擲異常
        log.info("assumpFail的assumeTrue執行完成");
        // 接下來是常規的單元測試邏輯,但因為前面丟擲了異常,就不再執行了
        assertEquals(2, Math.addExact(1,1));
    }
}
  1. 點選下圖紅框位置執行單元測試:

在這裡插入圖片描述
3. 執行結果如下:

在這裡插入圖片描述
4. 另外,在target目錄,可以看到surefire外掛生成的單元測試報告TEST-com.bolingcavalry.assertassume.service.impl.AssertAssumpTest.xml,如下圖所示,testcase節點中出現了skipped節點:

在這裡插入圖片描述

  • 上述對比驗證再次說明Assertions和Assumptions的區別:都用來對比預期值和實際值,當預期值和實際值不一致時,Assertions的測試結果是執行失敗,Assumptions的測試結果是跳過(或者忽略);

Assumptions實戰

弄清楚的Assertions和Assumptions的區別,接下來趁熱打鐵,學習Assumptions類中幾個重要的靜態方法:assumeTrue、assumingThat

  1. 最簡單的用法如下,可見只有assumeTrue不丟擲異常,後面的log.info才會執行:
    @Test
    @DisplayName("最普通的assume用法")
    void tryAssumeTrue() {
        assumeTrue("CI".equals(envType));

        log.info("CI環境才會列印的assumeTrue");
    }
  1. assumeTrue可以接受Supplier型別作為第二個入參,如果assumeTrue失敗就會將第二個引數的內容作為失敗提示:
@Test
    @DisplayName("assume失敗時帶自定義錯誤資訊")
    void tryAssumeTrueWithMessage() {
        // 第二個入參是Supplier實現,返回的內容用作跳過用例時的提示資訊
        assumeTrue("CI".equals(envType),
                () -> "環境不匹配而跳過,當前環境:" + envType);

        log.info("CI環境才會列印的tryAssumeTrueWithMessage");
    }

效果如下圖:

在這裡插入圖片描述
3. 還有個assumingThat方法,可以接受Executable型別作為第二個入參,如果第一個入參為true就會執行Executable的execute方法,注意assumingThat方法的特點:不丟擲異常,因此其所在的方法不會被跳過,這是和assumeTrue相比最大的區別(assumeTrue一旦入參為false就會丟擲異常,其所在方法就被標記為跳過):

    @Test
    @DisplayName("assume成功時執行指定邏輯")
    void tryAssumingThat() {
        // 第二個入參是Executable實現,
        // 當第一個引數為true時,執行第二個引數的execute方法
        assumingThat("CI".equals(envType),
                () -> {
                    log.info("這一行內容只有在CI環境才會列印");
                });

        log.info("無論什麼環境都會列印的tryAssumingThat");
    }
  • 接下來我們們執行上述程式碼,看看效果;

執行Assumptions程式碼

  1. 先做準備工作,本次實戰的springboot工程名為assertassume,我們們在工程的resources目錄下新增兩個配置檔案:application.properties和application-test.properties,位置如下圖:

在這裡插入圖片描述
2. application-test.properties內容如下:

envType:CI
  1. application.properties內容如下:
envType:PRODUCTION
  1. 完整的單元測試類如下,通過註解ActiveProfiles,指定了使用application-test.properties的配置,因此envType的值為CI
package com.bolingcavalry.assertassume.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.jupiter.api.Assumptions.assumingThat;

@SpringBootTest
@Slf4j
@ActiveProfiles("test")
public class AssumptionsTest {

    @Value("${envType}")
    private String envType;

    @Test
    @DisplayName("最普通的assume用法")
    void tryAssumeTrue() {
        assumeTrue("CI".equals(envType));

        log.info("CI環境才會列印的assumeTrue");
    }

    @Test
    @DisplayName("assume失敗時帶自定義錯誤資訊")
    void tryAssumeTrueWithMessage() {
        // 第二個入參是Supplier實現,返回的內容用作跳過用例時的提示資訊
        assumeTrue("CI".equals(envType),
                () -> "環境不匹配而跳過,當前環境:" + envType);

        log.info("CI環境才會列印的tryAssumeTrueWithMessage");
    }

    @Test
    @DisplayName("assume成功時執行指定邏輯")
    void tryAssumingThat() {
        // 第二個入參是Executable實現,
        // 當第一個引數為true時,執行第二個引數的execute方法
        assumingThat("CI".equals(envType),
                () -> {
                    log.info("這一行內容只有在CI環境才會列印");
                });

        log.info("無論什麼環境都會列印的tryAssumingThat");
    }
}
  1. 執行結果如下圖,可見assume通過,所有資訊都被列印出來了:

在這裡插入圖片描述

  1. 接下來把程式碼中的ActiveProfiles註解那一行註釋掉,如下圖紅框:

在這裡插入圖片描述

  1. 執行結果如下,可見tryAssumingThat方法被標記為成功,不過從日誌可見assumingThat的第二個入參executable沒有被執行:

在這裡插入圖片描述

  • 至此,Assumptions類的常用方法體驗完成,接下來的章節會繼續學習其他常用類;

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 資料庫+中介軟體系列
  6. DevOps系列

歡迎關注公眾號:程式設計師欣宸

微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos

相關文章