[JUnit] JUnit5 基础 3 - 依赖注入,假设(assume),开启/禁用测试 与 嵌套测试

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JUnit] JUnit5 基础 3 - 依赖注入,假设(assume),开启/禁用测试 与 嵌套测试相关的知识,希望对你有一定的参考价值。

[JUnit] JUnit5 基础 3 - 依赖注入,假设(assume),开启/禁用测试 与 嵌套测试

Dependency Injection

在 Junit5 之前,Junit 对于在测试构造函数或方法中传参数支持不是很好,但是 Junit5 允许向构造函数与方法中传入元数据,因此也能在测试方法/构造函数中使用依赖注入。

如 Junit5 内置的 TestInfo 对象,就可以通过 DI 的方式在运行时获取:

package com.example;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

@DisplayName("App Test with spaces")
public class AppTest
{
    @BeforeAll
    public static void beforeAll(TestInfo testInfo){
        System.out.println("********* execute beforeAll() *********");
        System.out.println("Display name - " + testInfo.getDisplayName());
        System.out.println("Test Class   - " + testInfo.getTestClass());
        System.out.println("Test Method  - " + testInfo.getTestMethod());
        System.out.println("****************************************");
    }

    public AppTest(TestInfo testInfo) {
        System.out.println("********* execute constructor **********");
        System.out.println("Display name - " + testInfo.getDisplayName());
        System.out.println("Test Class   - " + testInfo.getTestClass());
        System.out.println("Test Method  - " + testInfo.getTestMethod());
        System.out.println("****************************************");
    }

    @BeforeEach
    public void BeforeEach(TestInfo testInfo) {
        System.out.println("********* execute beforeEach() *********");
        System.out.println("Display name - " + testInfo.getDisplayName());
        System.out.println("Test Class   - " + testInfo.getTestClass());
        System.out.println("Test Method  - " + testInfo.getTestMethod());
        System.out.println("****************************************");
    }

    @Test
    public void testOne(TestInfo testInfo) {
        System.out.println("********* execute testOne() ***********");
        System.out.println("Display name - " + testInfo.getDisplayName());
        System.out.println("Test Class   - " + testInfo.getTestClass());
        System.out.println("Test Method  - " + testInfo.getTestMethod());
        System.out.println("****************************************");
    }
}

运行结果为:

通过依赖注入,TestInfo 在运行时对于不同的显示名称、方法能够自行判断,而非用户手动声明的方式去进行判断。

假设(Assume)

除了 断言(assert) 之外,Junit5 也能通过 假设(assume) 对值进行判断。

assumeTrue & assumeFalse

package com.example;

import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

import org.junit.jupiter.api.Test;

public class AppTest
{
    @Test
    void testAssumeTrue() {
        int num1 = 1, num2 = 1;
        assumeTrue(num1 == num2);
    }

    @Test
    void testAssumeTrueFail() {
        int num1 = 1, num2 = 1;
        assumeTrue(num1 != num2, "assumption fail");
    }

    @Test
    void testAssumeFalse() {
        int num1 = 1, num2 = 1;
        assumeFalse(num1 != num2);
    }
}

运行结果:

assumeThat

package com.example;

import static org.junit.jupiter.api.Assumptions.assumingThat;

import org.junit.jupiter.api.Test;

public class AppTest
{
    @Test
    void testAssumeThat1() {
        int val1 = 1, val2 = 0;
        assumingThat(val1 == val2, () -> {
            System.out.println("working on this part");
        });
    }

    @Test
    void testAssumeThat2() {
        int val1 = 1, val2 = 0;
        assumingThat(val1 != val2, () -> {
            System.out.println("will skip this part");
        });

        System.out.println("still print this line");
    }
}

运行结果:

assume 的应用场景

乍一看 assumeassert 好像没有什么区别,但是 assumeTrueassumeFalse 中,testAssumeTrueFail() 函数的旁边不是一个 ❌,而是一个 ❔,这是因为 Junit5 跳过了这个方法,直接进行下一个测试方法。而使用 assert 的话,Junit5 就会判断这个测试方法失败,直接返回 ❌。

assumingThat 方法中,差别更加明显,尽管 testAssumeThat2()assumingThat 的判断是错误的,但是该测试方法并没有终止,而是跳过了 assumingThat 中的内容,直接跳到了下一行代码,并且进行了输出。

这也使得 assume 的应用场景较为的明确:它可以用于对不同环境的测试,如:

package com.example;

import static org.junit.jupiter.api.Assumptions.assumingThat;

import org.junit.jupiter.api.Test;

public class AppTest
{
    @Test
    void testAssumeTha2() {
        System.setProperty("ENV", "DEV");
        assumingThat("DEV".equals(System.getProperty("ENV")), () -> {
            // 使用 assert 进行测试
        });

        System.out.println("运行所有环境下都要运行的测试");
    }
}

开启与禁用测试

禁用测试

@Disabled 注释可以用来禁用测试:

package com.example;

import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

@Disabled
public class AppTest
{
    @Test
    void test1() {
        assertTrue(1 == 2);
    }

    @Test
    void test2() {
        assertTrue(1 == '1');
    }
}

其运行结果如下:

可以从左边的测试界面看到,Junit 直接跳过了所有的测试,没有表示成功也没有表示失败。

同样,@Disabled 也可以用在方法上,当挂载在方法上是,它会跳过当前的测试方法,进行下一个测试。

开启/禁用 OS

该方法可以使得测试方法不在具体的 OS 上运行,如:

package com.example;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

public class AppTest
{
    @Test
    void test1() {
        System.out.println("Linux/MacOS/Windows");
    }

    @DisabledOnOs(OS.MAC)
    @Test
    void test2() {
        System.out.println("Linux/Windows");
    }

    @DisabledOnOs(OS.WINDOWS)
    @Test
    void test3() {
        System.out.println("Linux/MacOS");
    }
}

我的系统是 Windows,所以 test3() 就会被禁用了:

@DisabledOnOs(),同样也有 @EnabledOnOs()

开启/禁用 JRE

这条与开启禁用 OS 的配置相似,都是让测试方法在指定的 JRE 环境下运行。

系统属性条件

这指的是 SystemProperty变量,对应的注释为 @DisabledIfSystemProperty@EnabledIfSystemProperty

package com.example;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;

public class AppTest
{
    @DisabledIfSystemProperty(named="os.name", matches="Windows 10")
    @Test
    void test2() {
        System.out.println("not windows 10");
    }
}

运行结果:

环境变量条件

与系统属性条件的使用方法相似,其注解为:@DisabledIfEnvironmentVariable@EnabledIfEnvironmentVariable

嵌套测试

嵌套测试,即使用匿名类进行嵌套测试。

package com.example;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class AppTest
{
    @Test
    void test() {
        System.out.println("outer");
    }

    @Nested
    class NestedClass {
        @Test
        void test2() {
            System.out.println("nested inner");
        }
    }
}

运行结果如下:

以上是关于[JUnit] JUnit5 基础 3 - 依赖注入,假设(assume),开启/禁用测试 与 嵌套测试的主要内容,如果未能解决你的问题,请参考以下文章

JUnit5 快速指南

在Maven项目中运行JUnit 5测试用例

[JUnit] JUnit5 基础 1 - Junit5 结构 与 断言的使用

Junit5测试无法注入依赖但正常运行的应用程序可以注入它

使用 spring boot gradle 插件无法使用依赖管理执行 junit5 测试

当 pom.xml 中存在 TestContainers 依赖项时,未检测到 JUnit 5 测试