单元测试之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;
    }
}

 

  

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