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 的测试用例
自从有了类似 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。
注解
除非另有说明,所有核心注释都位于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的一些区别:
断言
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
上一篇: Java从入门到放弃系列