單元測試之JUnit5介紹

1. JUnit5簡介

      JUnit5官網

     與以前的JUnit版本不同,JUnit 5由三個不同子項目的幾個不同模塊組成:

     JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

     JUnit Platform:JUnit Platform 可以作爲launching testing frameworks在JVM上的一個基礎,此外,該平臺還提供了一個 控制檯啓動器( Console Launcher)(用於從命令行啓動該平臺)和一個 基於JUnit 4的運行器JUnit 4 based Runner )用於TestEngine在基於JUnit 4的環境中在平臺上運行任何應用程序。流行的IDE(請參閱IntelliJ IDEAEclipse, NetBeansVisual Studio Code)和構建工具(請參閱GradleMaven和 Ant)中 也存在對JUnit平臺的一流支持。

     JUnit Jupiter:JUnit Jupiter是新的編程模型( programming model )和 擴展模型 (extension model)的組合,用於在JUnit 5中編寫測試和擴展。Jupiter子項目提供了一個TestEngine在平臺上運行基於Jupiter的測試的功能。

    JUnit Vintage:JUnit Vintage提供了一個TestEngine在平臺上運行基於JUnit 3和JUnit 4的測試的功能。

    注:JUnit 5在運行時需要Java 8(或更高版本)。然而,您仍然可以測試使用JDK早期版本編譯的代碼。

JUnit5測試的模塊架構說明表
子項目名 子項目概要介紹 模塊架構圖
JUnit Platform 用於JVM上啓動測試架構的基礎服務,提供命令行,IDE和構建工具等方式執行測試的支持。
JUnit Jupiter 包含JUnit5新的編程模型和擴展模型,主要是用於編寫測試代碼和擴展代碼。
JUnit Vintage 用於在JUnit5中兼容運行,JUnit3.x和JUnit4.x的測試用例。

2. JUnit5中三個不同子項目的依賴關係圖

JUnit5中三個不同子項目的依賴關係圖

3. JUnit5之JUnit Jupiter支持的用於配置的測試和擴展框架的註解表     

註解 描述

@Test

表示方法是測試方法。與JUnit 4的@Test註釋不同,此註釋不聲明任何屬性,因爲JUnit Jupiter中的測試擴展基於其自己的專用註釋進行操作。除非重寫這些方法,否則它們將繼承

@ParameterizedTest

表示方法是參數化測試。除非重寫這些方法,否則它們將繼承

@RepeatedTest

表示方法是重複測試的測試模板。除非重寫這些方法,否則它們將繼承

@TestFactory

表示方法是用於動態測試的測試工廠。除非重寫這些方法,否則它們將繼承

@TestTemplate

表示方法是測試用例模板,測試用例設計爲根據已註冊提供程序返回的調用上下文的數量被多次調用。除非重寫這些方法,否則它們將繼承

@TestMethodOrder

用於配置帶註釋的測試類的測試方法執行順序;類似於JUnit 4的@FixMethodOrder。這樣的註釋是繼承的

@TestInstance

用於爲帶註釋的測試類配置測試實例生命週期。這樣的註釋是繼承的

@DisplayName

聲明測試類或測試方法的自定義顯示名稱。這樣的註釋不是繼承的

@DisplayNameGeneration

聲明測試類的自定義顯示名稱生成器。這樣的註釋是繼承的

@BeforeEach

表示該註釋的方法應該被執行之前 的每個 @Test@RepeatedTest@ParameterizedTest,或@TestFactory方法在當前類; 類似於JUnit 4的@Before。除非重寫這些方法,否則它們將繼承

@AfterEach

表示該註釋的方法應該被執行之後 每個 @Test@RepeatedTest@ParameterizedTest,或@TestFactory方法在當前類; 類似於JUnit 4的@After。除非重寫這些方法,否則它們將繼承

@BeforeAll

表示該註釋的方法應該被執行之前 所有 @Test@RepeatedTest@ParameterizedTest,和@TestFactory方法在當前類; 類似於JUnit 4的@BeforeClass。此類方法是繼承的(除非它們被隱藏重寫),並且必須被繼承(除非static使用“每類” 測試實例生命週期)。

@AfterAll

表示該註釋的方法應該被執行之後 的所有 @Test@RepeatedTest@ParameterizedTest,和@TestFactory方法在當前類; 類似於JUnit 4的@AfterClass。此類方法是繼承的(除非它們被隱藏重寫),並且必須被繼承(除非static使用“每類” 測試實例生命週期)。

@Nested

表示帶註釋的類是一個非靜態的嵌套測試類@BeforeAll@AfterAll方法不能直接在使用@Nested測試類除非“每級” 測試實例的生命週期被使用。這樣的註釋不是繼承的

@Tag

用於在類或方法級別聲明用於過濾測試的標籤;類似於TestNG中的測試組或JUnit 4中的類別。此類註釋在類級別繼承,而不在方法級別繼承

@Disabled

用於禁用測試類或測試方法;類似於JUnit 4的@Ignore。這樣的註釋不是繼承的

@Timeout

如果執行超過給定的持續時間,則使測試,測試工廠,測試模板或生命週期方法失敗。這樣的註釋是繼承的

@ExtendWith

用於聲明性註冊擴展名。這樣的註釋是繼承的

@RegisterExtension

用於通過字段以編程方式註冊擴展。除非被遮蓋,否則這些字段將被繼承

@TempDir

用於通過生命週期方法或測試方法中的字段注入或參數注入來提供臨時目錄;位於org.junit.jupiter.api.io包裝中。

      注:除非另有說明,否則所有核心註釋都位於模塊的org.junit.jupiter.api包中junit-jupiter-api。一些註釋當前可能是實驗性的。有關詳細信息,請參考實驗API中的表格 。

4. JUnit5中的斷言

斷言 描述
assertAll 斷言組
assertEquals 判斷相等
assertTrue 判斷爲真
assertNotNull 判斷非空
assertThrows 拋出異常
assertTimeout 超時
assertTimeoutPreemptively 超時

5. JUnit5在Gradle項目中和Maven項目中的依賴關係

JUnit5在Gradle和maven項目中的依賴
項目類別 相關依賴

Gradle項目

(build.gradle)

plugins {
    id 'java'
    id 'eclipse' // optional (to generate Eclipse project files)
    id 'idea' // optional (to generate IntelliJ IDEA project files)
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.5.2')
}

test {
    useJUnitPlatform()
    testLogging {
        events "passed", "skipped", "failed"
    }
}

Maven項目

(project.pom)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>junit5-jupiter-starter-maven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
        <junit.jupiter.version>5.5.2</junit.jupiter.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

6. JUnit5測試框架的特性及其應用

      6.1 JUnit5測試框架的特性

  • 提供全新的斷言和測試註解,支持測試類內嵌。
  • 更豐富的測試方式:支持動態測試,重複測試,參數化測試等。
  • 實現了模塊化,讓測試執行和測試發現等不同模塊解耦,減少依賴。

  • 提供對 Java 8 的支持,如 Lambda 表達式,Sream API等。

     6.2 JUnit5測試框架的應用

@DisplayName("我的第一個測試用例")
public class MyFirstTestCaseTest {

    @BeforeAll
    public static void init() {
        System.out.println("初始化數據");
    }

    @AfterAll
    public static void cleanup() {
        System.out.println("清理數據");
    }

    @BeforeEach
    public void tearup() {
        System.out.println("當前測試方法開始");
    }

    @AfterEach
    public void tearDown() {
        System.out.println("當前測試方法結束");
    }

    @DisplayName("我的第一個測試")
    @Test
    void testFirstTest() {
        System.out.println("我的第一個測試開始測試");
    }

    @DisplayName("我的第二個測試")
    @Test
    void testSecondTest() {
        System.out.println("我的第二個測試開始測試");
    }
}
基於JUnit5的註解測試案例表
測試註解 註解解析 測試方法 測試結果
@DisplayName("顯示名稱 ")

 @DisplayName 設置的名稱,這個註解就是 JUnit 5 引入,用來定義一個測試類並指定用例在測試報告中的展示名稱,這個註解可以使用在類上和方法上,在類上使用它就表示該類爲測試類,在方法上使用則表示該方法爲測試方法。即聲明測試類或測試方法的自定義顯示名稱

@DisplayName("我的第一個測試") @Test void testFirstTest() { System.out.println("我的第一個測試開始測試"); }
@BeforeAll 表示使用了該註解的方法應該在當前類中所有使用了@Test @RepeatedTest、@ParameterizedTest或者@TestFactory註解的方法之前執行一次; @BeforeAll public static void init() { System.out.println("初始化數據"); }
@AfterAll 表示使用了該註解的方法應該在當前類中所有使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory註解的方法之後執行一次; @AfterAll public static void cleanup() { System.out.println("清理數據"); }
@BeforeEach 表示使用了該註解的方法應該在當前類中每一個使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory註解的方法之前執行 @BeforeEach public void tearup() { System.out.println("當前測試方法開始"); }
@AfterEach 表示使用了該註解的方法應該在當前類中每一個使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory註解的方法之後 執行 @AfterEach public void tearDown() { System.out.println("當前測試方法結束"); }
@Test 表示該方法是一個測試方法。JUnit5與JUnit 4的@Test註解不同的是,它沒有聲明任何屬性,因爲JUnit Jupiter中的測試擴展是基於它們自己的專用註解來完成的。這樣的方法會被繼承,除非它們被覆蓋 @DisplayName("我的第二個測試") @Test void testSecondTest() { System.out.println("我的第二個測試開始測試"); }

@Disabled(禁止執行測試)

當我們希望在運行測試類時,跳過某個測試方法,正常運行其他測試用例時,我們就可以用上 @Disabled 註解,表明該測試方法處於不可用,執行測試類的測試方法時不會被 JUnit 執行。 @DisplayName("我的第三個測試") @Disabled @Test void testThirdTest() { System.out.println("我的第三個測試開始測試"); }

@Nested

(內嵌套測試)

當我們編寫的類和代碼逐漸增多,隨之而來的需要測試的對應測試類也會越來越多。爲了解決測試類數量爆炸的問題,JUnit 5提供了@Nested 註解,能夠以靜態內部成員類的形式對測試用例類進行邏輯分組。 並且每個靜態內部類都可以有自己的生命週期方法, 這些方法將按從外到內層次順序執行。 此外,嵌套的類也可以用@DisplayName 標記,這樣我們就可以使用正確的測試名稱

@DisplayName("內嵌測試類")

public class NestUnitTest { @BeforeEach

void init() { System.out.println("測試方法執行前準備"); }

@Nested

@DisplayName("第一個內嵌測試類") class FirstNestTest {

@Test

void test() { System.out.println("第一個內嵌測試類執行測試"); } } @Nested

@DisplayName("第二個內嵌測試類") class SecondNestTest {

@Test

void test() { System.out.println("第二個內嵌測試類執行測試"); } } }

@RepeatedTest(重複性測試)

 JUnit 5 裏新增了對測試方法設置運行次數的支持,允許讓測試方法進行重複運行。當要運行一個測試方法 N次時,可以使用 @RepeatedTest 標記它。

@DisplayName("重複測試") @RepeatedTest(value = 3)

public void i_am_a_repeated_test() { System.out.println("執行測試"); }

        表格中的@RepeatedTest是基本的用法,我們還可以對重複運行的測試方法名稱進行修改,利用 @RepeatedTest 提供的內置變量,以佔位符方式在其 name 屬性上使用,下面先看下使用方式和效果:

@DisplayName("自定義名稱重複測試")
@RepeatedTest(value = 3, name = "{displayName} 第 {currentRepetition} 次")
public void i_am_a_repeated_test_2() {
    System.out.println("執行測試");
}

        @RepeatedTest 註解內用 currentRepetition 變量表示已經重複的次數,totalRepetitions 變量表示總共要重複的次數,displayName 變量表示測試方法顯示名稱,我們直接就可以使用這些內置的變量來重新定義測試方法重複運行時的名稱。

7. JUnit4與JUnit5常用註解對比

8. 新的斷言

在斷言 API 設計上,JUnit 5 進行顯著地改進,並且充分利用 Java 8 的新特性,特別是 Lambda 表達式,最終提供了新的斷言類: org.junit.jupiter.api.Assertions 。許多斷言方法接受 Lambda 表達式參數,在斷言消息使用 Lambda 表達式的一個優點就是它是延遲計算的,如果消息構造開銷很大,這樣做一定程度上可以節省時間和資源。

現在還可以將一個方法內的多個斷言進行分組,使用 assertAll 方法如下示例代碼:

@Test
void testGroupAssertions() {
    int[] numbers = {0, 1, 2, 3, 4};
    Assertions.assertAll("numbers",
            () -> Assertions.assertEquals(numbers[1], 1),
            () -> Assertions.assertEquals(numbers[3], 3),
            () -> Assertions.assertEquals(numbers[4], 4)
    );
}

如果分組斷言中任一個斷言的失敗,都會將以 MultipleFailuresError 錯誤進行拋出提示。

9. 超時操作的測試:assertTimeoutPreemptively

當我們希望測試耗時方法的執行時間,並不想讓測試方法無限地等待時,就可以對測試方法進行超時測試,JUnit 5 對此推出了斷言方法 assertTimeout,提供了對超時的廣泛支持。

假設我們希望測試代碼在一秒內執行完畢,可以寫如下測試用例:

@Test
@DisplayName("超時方法測試")
void test_should_complete_in_one_second() {
  Assertions.assertTimeoutPreemptively(Duration.of(1, ChronoUnit.SECONDS), () -> Thread.sleep(2000));
}

這個測試運行失敗,因爲代碼執行將休眠兩秒鐘,而我們期望測試用例在一秒鐘之內成功。但是如果我們把休眠時間設置一秒鐘,測試仍然會出現偶爾失敗的情況,這是因爲測試方法執行過程中除了目標代碼還有額外的代碼和指令執行會耗時,所以在超時限制上無法做到對時間參數的完全精確匹配。

10. 異常測試:assertThrows

我們代碼中對於帶有異常的方法通常都是使用 try-catch 方式捕獲處理,針對測試這樣帶有異常拋出的代碼,而 JUnit 5 提供方法 Assertions#assertThrows(Class<T>, Executable) 來進行測試,第一個參數爲異常類型,第二個爲函數式接口參數,跟 Runnable 接口相似,不需要參數,也沒有返回,並且支持 Lambda表達式方式使用,具體使用方式可參考下方代碼:

@Test
@DisplayName("測試捕獲的異常")
void assertThrowsException() {
  String str = null;
  Assertions.assertThrows(IllegalArgumentException.class, () -> {
    Integer.valueOf(str);
  });
}

當Lambda表達式中代碼出現的異常會跟首個參數的異常類型進行比較,如果不屬於同一類異常,就會控制檯輸出如下類似的提示:org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected: <IllegalArgumentException> but was: <...Exception>

11. JUnit 5 參數化測試

要使用 JUnit 5 進行參數化測試,除了 junit-jupiter-engine 基礎依賴之外,還需要另個模塊依賴:junit-jupiter-params,其主要就是提供了編寫參數化測試 API。同樣方式,把相同版本的對應依賴引入 Maven 工程中:

<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-params</artifactId>
  <version>5.5.2</version>
  <scope>test</scope>
</dependency>

12. 基本數據源測試: @ValueSource

@ValueSource 是 JUnit 5 提供的最簡單的數據參數源,支持 Java 的八大基本類型和字符串,Class,使用時賦值給註解上對應類型屬性,以數組方式傳遞,示例代碼如下:

public class ParameterizedUnitTest {
    @ParameterizedTest
    @ValueSource(ints = {2, 4, 8})
    void testNumberShouldBeEven(int num) {
        Assertions.assertEquals(0, num % 2);
    }

    @ParameterizedTest
    @ValueSource(strings = {"Effective Java", "Code Complete", "Clean Code"})
    void testPrintTitle(String title) {
        System.out.println(title);
    }
}

@ParameterizedTest 作爲參數化測試的必要註解,替代了 @Test 註解。任何一個參數化測試方法都需要標記上該註解。

運行測試,結果如下圖所示,針對 @ValueSource 裏每個參數都會運行目標方法,一旦哪個參數運行測試失敗,就意味着該測試方法不通過。

13. CSV 數據源測試:@CsvSource

通過 @CsvSource 可以注入指定 CSV 格式 (comma-separated-values) 的一組數據,用每個逗號分隔的值來匹配一個測試方法對應的參數,下面是使用示例:

@ParameterizedTest
@CsvSource({"1,One", "2,Two", "3,Three"})
void testDataFromCsv(long id, String name) {
    System.out.printf("id: %d, name: %s", id, name);
}

運行結果如圖所示,除了用逗號分隔參數外,@CsvSource 還支持自定義符號,只要修改它的 delimiter 即可,默認爲 

JUnit 還提供了讀取外部 CSV 格式文件數據的方式作爲數據源的實現,我們只要用 @CsvFileSource 指定資源文件路徑即可,使用起來跟 @CsvSource 一樣簡單這裏就不再重複演示了。

@CsvFileSource 指定的資源文件路徑時要以 / 開始,尋找當前測試資源目錄下文件。

除了上面提到的三種數據源方式外,JUnit 還提供了以下三種數據源:

  • @EnumSource:允許我們通過參數值,給指定 Enum 枚舉類型傳入,構造出枚舉類型中特定的值。
  • @MethodSource:指定一個返回的 Stream / Array / 可迭代對象 的方法作爲數據源。 需要注意的是該方法必須是靜態的,並且不能接受任何參數。
  • @ArgumentSource:通過實現 ArgumentsProvider 接口的參數類來作爲數據源,重寫它的 provideArguments 方法可以返回自定義類型的 Stream<Arguments> ,作爲測試方法所需要的數據使用。

附加:適用Stream<Arguments>進行參數化測試的代碼示例

package com.test.atchk.blockchain.chaincode.contract;

import com.test.atchk.blockchain.chaincode.builder.CampaignBeBuilder;
import com.test.atchk.blockchain.chaincode.builder.FulfilledBeResultBuilder;
import com.test.atchk.blockchain.chaincode.builder.TestBuilder;
import com.test.atchk.blockchain.chaincode.enumeration.StateEventStatus;
import com.test.atchk.blockchain.chaincode.model.*;
import com.test.atchk.blockchain.chaincode.service.CampaignBeService;
import com.test.atchk.blockchain.chaincode.service.CsService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class CampaignBeahaviourSpendWithTxnValueTestV2 {

    //the service of the test
    CampaignBeService testBeService;

    //the the arguments of the method
    String testID = "CAMPAIGN001";
    String testKey = "TEAM001";
    List<String> tests = Arrays.asList("MEM001");
    String testEnrolDate = OffsetDateTime.now().minusDays(7).toString();

    //Txn ID
    String currentTestID = "TXN001";
    String currentTestID1 = "TXN002";
    String currentTestID2 = "TXN003";

    //BeRestriction
    CaTestDTO.BeRestriction totalNumOfTimesRestriction;
    CaTestDTO.BeRestriction qualifyingMinimumTxnValue;
    CaTestDTO.BeRestriction qualifyingLatLngRestriction;
    CaTestDTO.BeRestriction qualifyingPaymentTypeRestriction;
    CaTestDTO.BeRestriction qualifyingDaysOfWeekRestriction;
    CaTestDTO.BeRestriction qualifyingTimeOfDayRestriction;
    CaTestDTO.BeRestriction qualifyingTimeFrameRestriction;
    CaTestDTO.BeRestriction prerequisiteBeRestriction;

    //builder the expected outcomes
    List<OutcomeDTO> expectedOutcomes = Arrays.asList(new OutcomeDTO()
            .setAmount(new BigDecimal(100))
            .setOrigin(new OutcomeDTO.Origin("OUTCOME001", "", "",  "")) // TODO: [assignee:Fiona] help fill in testID and TeamID, and txnIDs
                    .setMemberId("MEM001")
            .setType("point"));

    //builder the expected result
    FulfilledBeResult expectGetResults = FulfilledBeResultBuilder.fulfilledBeResultResult(true, Arrays.asList(currentTestID, currentTestID1, currentTestID2), expectedOutcomes);
    FulfilledBeResult expectNoResults = FulfilledBeResultBuilder.fulfilledBeResultResult(false, new ArrayList<>(), null);

    @BeforeAll
    public void setUp() {
        testBeService = CampaignBeService.getInstance();

        totalNumOfTimesRestriction = CampaignBeBuilder.buildTotalNumOfTimesEventRestriction("totalNumEvent_001", 3, true);
        qualifyingLatLngRestriction = CampaignBeBuilder.buildQualifyingLatLngTxnRestriction("LatLng_001", new BigDecimal(1), new BigDecimal(2), new BigDecimal(3));
        qualifyingPaymentTypeRestriction = CampaignBeBuilder.buildQualifyingPaymentTypeTxnRestriction("PAYMENT_001", "cash");
        qualifyingDaysOfWeekRestriction = CampaignBeBuilder.buildQualifyingDaysOfWeekTxnRestriction("Days_Of_WEEK_ID_001", Arrays.asList(
                DayOfWeek.MONDAY,
                DayOfWeek.TUESDAY,
                DayOfWeek.WEDNESDAY,
                DayOfWeek.THURSDAY,
                DayOfWeek.FRIDAY,
                DayOfWeek.SATURDAY,
                DayOfWeek.SUNDAY
        ));
        qualifyingTimeOfDayRestriction = CampaignBeBuilder.buildQualifyingTimeOfDayTxnRestriction("TIME_Of_DAY_001", Arrays.asList(
                new TimeOfDayDTO().setFrom("08:10").setTo("10:14"),
                new TimeOfDayDTO().setFrom("20:11").setTo("23:59")
        ));
        qualifyingTimeFrameRestriction = CampaignBeBuilder.buildQualifyingTimeframeTxnRestriction("TIME_FRAME_ID_001", 123456);
        prerequisiteBeRestriction = CampaignBeBuilder.buildPrerequisiteBeEventRestriction("prerequisiteBe_001", "A", false);
        qualifyingMinimumTxnValue = CampaignBeBuilder.buildQualifyingMinimumTxnValueTxnRestriction("Min_NumTxn_001", new BigDecimal(100));
    }

    Stream<Arguments> providerTheTestArgumentsOfPas() {

        CaTestDTO.BeEvent beEvent_4_1_1 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", false, totalNumOfTimesRestriction, qualifyingMinimumTxnValue);
        CaTestDTO.Be be_4_1_1 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_1, new BigDecimal(100));
 
        CaTestDTO.BeEvent beEvent_4_1_2 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", false, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(qualifyingLatLngRestriction);
        CaTestDTO.Be be_4_1_2 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_2, new BigDecimal(100));
  
        CaTestDTO.BeEvent beEvent_4_1_3 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", false, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(qualifyingPaymentTypeRestriction);
        CaTestDTO.Be be_4_1_3 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_3, new BigDecimal(100));
 
        CaTestDTO.BeEvent beEvent_4_1_4 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", false, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(qualifyingDaysOfWeekRestriction);
        CaTestDTO.Be be_4_1_4 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_4, new BigDecimal(100));
   
        CaTestDTO.BeEvent beEvent_4_1_5 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", true, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(qualifyingTimeOfDayRestriction);
        CaTestDTO.Be be_4_1_5 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_5, new BigDecimal(100));

        CaTestDTO.BeEvent beEvent_4_1_6 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", true, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(qualifyingTimeFrameRestriction);
        CaTestDTO.Be be_4_1_6 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_6, new BigDecimal(100));
   
        CaTestDTO.BeEvent beEvent_4_1_7 = CampaignBeBuilder.buildPurchaseSpendWithTestValue("CAMPAIGN001", false, totalNumOfTimesRestriction, qualifyingMinimumTxnValue).addRestriction(prerequisiteBeRestriction);
        CaTestDTO.Be be_4_1_7 = CampaignBeBuilder.buildBeWithSingleEventWithFixedPointOutcome("Behave001", beEvent_4_1_7, new BigDecimal(100));

        return Stream.of(

                Arguments.of(this.transactionTest_4_1_1_GetResult(),be_4_1_1,expectGetResults),

                Arguments.of(this.transactionTest_4_1_1_NoResult(),be_4_1_1,expectNoResults),

                Arguments.of(this.transactionTest_4_1_2_GetResult(),be_4_1_2,expectGetResults),

                Arguments.of(this.transactionTest_4_1_2_NoResult(),be_4_1_2,expectNoResults),

                Arguments.of(this.transactionTest_4_1_3_GetResult(),be_4_1_3,expectGetResults),

                Arguments.of(this.transactionTest_4_1_3_NoResult(),be_4_1_3,expectNoResults),

                Arguments.of(this.transactionTest_4_1_4_GetResult(),be_4_1_4,expectGetResults),

                Arguments.of(this.transactionTest_4_1_4_NoResult(),be_4_1_4,expectNoResults),

                Arguments.of(this.transactionTest_4_1_5_GetResult(),be_4_1_5,expectGetResults),

                Arguments.of(this.transactionTest_4_1_5_NoResult(),be_4_1_5,expectNoResults),

                Arguments.of(this.transactionTest_4_1_6_GetResult(),be_4_1_6,expectGetResults),

                Arguments.of(this.transactionTest_4_1_6_NoResult(),be_4_1_6,expectNoResults),

                Arguments.of(this.transactionTest_4_1_7_GetResult(),be_4_1_7,expectGetResults),

                Arguments.of(this.transactionTest_4_1_7_NoResult(),be_4_1_7,expectNoResults)
        );
    }

    @ParameterizedTest
    @MethodSource("providerTheTestArgumentsOfPas")
    public void spendWithTxnValueTest(CpsDTO cps, CaTestDTO.Be be, FulfilledBeResult expectResult) {
        //testBeService.evaluateCampaignBe()爲真正需要測試的方法
FulfilledBeResult result = testBeService.evaluateCampaignBe(cps,
                be,
                tests,
                currentTestID1);
        Assertions.assertEquals(expectResult, result);
    }

    public CpsDTO transactionTest_4_1_1_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        );
        return  cps;
    }

    public CpsDTO transactionTest_4_1_1_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(3).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(9).toString())
                        .payment(100)
                        .build()
        );
       return cps;
    }

    public CpsDTO transactionTest_4_1_2_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .location("LatLng001", new BigDecimal(1), new BigDecimal(2))
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .location("LatLng001", new BigDecimal(1), new BigDecimal(2))
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .location("LatLng001", new BigDecimal(1), new BigDecimal(2))
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_2_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .location("LatLng_001", new BigDecimal(2), new BigDecimal(2))
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .location("LatLng_001", new BigDecimal(1), new BigDecimal(2))
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .location("LatLng_001", new BigDecimal(1), new BigDecimal(2))
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_3_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(new BigDecimal(100), "cash")
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(new BigDecimal(100), "cash")
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(new BigDecimal(100), "cash")
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_3_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(new BigDecimal(100), "cash")
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(new BigDecimal(100), "cash")
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(new BigDecimal(100), "alipay")
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_4_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_4_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(10).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_5_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, "2019-12-13T22:00:00+08:00")
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, "2019-12-12T22:00:00+08:00")
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, "2019-12-11T22:00:00+08:00")
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_5_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(10).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_6_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }

   
    public CpsDTO transactionTest_4_1_6_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(10).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }

    public CpsDTO transactionTest_4_1_7_GetResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        );
        cps.addEvent("A", new CpsDTO.StateEvent().setStatus(StateEventStatus.FULFILLED));

        return cps;
    }


    public CpsDTO transactionTest_4_1_7_NoResult() {

        CpsDTO cps = CsService.createNewPas(testID + ":" + testKey, testID, tests, testEnrolDate);

        cps.addTestDetails(
                new TestBuilder()
                        .basic(currentTestID, OffsetDateTime.now().minusDays(6).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID1, OffsetDateTime.now().minusDays(7).toString())
                        .payment(100)
                        .build()
        ).addTestDetails(
                new TestBuilder()
                        .basic(currentTestID2, OffsetDateTime.now().minusDays(8).toString())
                        .payment(100)
                        .build()
        );
        return cps;
    }
}

 

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章