欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Junit5单元测试

程序员文章站 2022-05-04 08:43:18
认识Junit 5JUnit 5 与以前版本的 JUnit 不同,拆分成由三个不同子项目的几个不同模块组成。JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit VintageJunit Platform: 用于JVM上启动测试框架的基础服务,提供命令行,IDE和构建工具等方式执行测试的支持。JUnit Jupiter: 包含 JUnit 5 新的编程模型和扩展模型,主要就是用于编写测试代码和扩展代码。Junit Vintage: 用于在JUnit 5...

认识Junit 5

JUnit 5 与以前版本的 JUnit 不同,拆分成由三个不同子项目的几个不同模块组成。
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

  • Junit Platform: 用于JVM上启动测试框架的基础服务,提供命令行,IDE和构建工具等方式执行测试的支持。
  • JUnit Jupiter: 包含 JUnit 5 新的编程模型和扩展模型,主要就是用于编写测试代码和扩展代码。
  • Junit Vintage: 用于在JUnit 5 中兼容运行 JUnit3.x 和 JUnit4.x 的测试用例
    Junit5单元测试

自从有了类似 JUnit 之类的测试框架,Java 单元测试领域逐渐成熟,开发人员对单元测试框架也有了更高的要求:更多的测试方式,更少的其他库的依赖。因此,大家期待着一个更强大的测试框架诞生,JUnit 作为Java测试领域的领头羊,推出了 JUnit 5 这个版本,主要特性:

  • 提供全新的断言和测试注解,支持测试类内嵌
  • 更丰富的测试方式:支持动态测试,重复测试,参数化测试等
  • 实现了模块化,让测试执行和测试发现等不同模块解耦,减少依赖
  • 提供对 Java 8 的支持,如 Lambda 表达式,Sream API等。

Junit 5常用用法

引入依赖

在SpringBoot2.3.1 release,包含在org.springframework.boot:spring-boot-starter-test中。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

在这里,去除了Juni4 API。
Junit5单元测试

注解

除非另有说明,所有核心注释都位于junit-jupiter-api模块中的org.junit.jupiter.api 包。

注解 描述
@Test 表示方法是测试方法。与JUnit 4的@Test注解不同,这个注解不声明任何属性,因为JUnit Jupiter中的测试扩展是基于它们自己专用的注解操作的。除非被重写,否则这些方法将被继承。
@ParameterizedTest 一个参数化的测试方法。除非被重写,否则这些方法将被继承。
@RepeatedTest Junit Jupiter通过用@RepeatedTest注释方法并指定所需的总重复次数,提供了将测试重复指定次数的能力。每次调用重复测试的行为都类似于执行常规的@Test方法,完全支持相同的生命周期回调和扩展。
@DisplayName 测试类和测试方法可以通过@DisplayName - - 声明自定义显示名称,其中包括空格、特殊字符,甚至表情符号(emojis)将显示在测试报告中以及测试运行程序和IDE中。
@BeforeEach 指示应在当前类中的每个@Test、@RepeatedTest、@ParameterizedTest或@TestFactory方法之前执行的方法
@AfterEach 指示应在当前类中的每个@Test、@RepeatedTest、@ParameterizedTest或@TestFactory方法之后执行的方法
@BeforeAll 指示应在当前类中的所有@Test、@RepeatedTest、@ParameterizedTest和@TestFactory方法之前执行的方法
@AfterAll 指示应在当前类中的所有@Test、@RepeatedTest、@ParameterizedTest和@TestFactory方法之后执行的方法

与 Junit 4的一些区别:

Junit5单元测试

断言

Junit Jupiter附带了Junit 4拥有的许多断言方法,并添加了一些适合与Java 8 lambdas一起使用的断言方法。所有Junit Jupiter断言都是 org.junit.jupiter.api.Assertions类下的静态方法。

import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.CountDownLatch;

import example.domain.Person;
import example.util.Calculator;

import org.junit.jupiter.api.Test;

class AssertionsDemo {

    private final Calculator calculator = new Calculator();

    private final Person person = new Person("Jane", "Doe");

    @Test
    void standardAssertions() {
        assertEquals(2, calculator.add(1, 1));
        assertEquals(4, calculator.multiply(2, 2),
                "The optional failure message is now the last parameter");
        assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "
                + "to avoid constructing complex messages unnecessarily.");
    }

    @Test
    void groupedAssertions() {
        // In a grouped assertion all assertions are executed, and all
        // failures will be reported together.
        assertAll("person",
            () -> assertEquals("Jane", person.getFirstName()),
            () -> assertEquals("Doe", person.getLastName())
        );
    }

    @Test
    void dependentAssertions() {
        // Within a code block, if an assertion fails the
        // subsequent code in the same block will be skipped.
        assertAll("properties",
            () -> {
                String firstName = person.getFirstName();
                assertNotNull(firstName);

                // Executed only if the previous assertion is valid.
                assertAll("first name",
                    () -> assertTrue(firstName.startsWith("J")),
                    () -> assertTrue(firstName.endsWith("e"))
                );
            },
            () -> {
                // Grouped assertion, so processed independently
                // of results of first name assertions.
                String lastName = person.getLastName();
                assertNotNull(lastName);

                // Executed only if the previous assertion is valid.
                assertAll("last name",
                    () -> assertTrue(lastName.startsWith("D")),
                    () -> assertTrue(lastName.endsWith("e"))
                );
            }
        );
    }

    @Test
    void exceptionTesting() {
        Exception exception = assertThrows(ArithmeticException.class, () ->
            calculator.divide(1, 0));
        assertEquals("/ by zero", exception.getMessage());
    }

    @Test
    void timeoutNotExceeded() {
        // The following assertion succeeds.
        assertTimeout(ofMinutes(2), () -> {
            // Perform task that takes less than 2 minutes.
        });
    }

    @Test
    void timeoutNotExceededWithResult() {
        // The following assertion succeeds, and returns the supplied object.
        String actualResult = assertTimeout(ofMinutes(2), () -> {
            return "a result";
        });
        assertEquals("a result", actualResult);
    }

    @Test
    void timeoutNotExceededWithMethod() {
        // The following assertion invokes a method reference and returns an object.
        String actualGreeting = assertTimeout(ofMinutes(2), AssertionsDemo::greeting);
        assertEquals("Hello, World!", actualGreeting);
    }

    @Test
    void timeoutExceeded() {
        // The following assertion fails with an error message similar to:
        // execution exceeded timeout of 10 ms by 91 ms
        assertTimeout(ofMillis(10), () -> {
            // Simulate task that takes more than 10 ms.
            Thread.sleep(100);
        });
    }

    @Test
    void timeoutExceededWithPreemptiveTermination() {
        // The following assertion fails with an error message similar to:
        // execution timed out after 10 ms
        assertTimeoutPreemptively(ofMillis(10), () -> {
            // Simulate task that takes more than 10 ms.
            new CountDownLatch(1).await();
        });
    }

    private static String greeting() {
        return "Hello, World!";
    }

}

本文地址:https://blog.csdn.net/u014427859/article/details/107684415