JUnit 5 介绍
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform是在JVM上 启动测试框架 的基础平台。它还定义了 TestEngine API,该API可用于开发在平台上运行的测试框架。此外,平台还提供了一个从命令行或者 Gradle 和 Maven 插件来启动的 控制台启动器 ,它就好比一个 基于JUnit 4的Runner 在平台上运行任何TestEngine。
JUnit Jupiter是一个组合体,它是由在JUnit 5中编写测试和扩展的新编程模型 和扩展模型组成。另外,Jupiter子项目还提供了一个TestEngine,用于在平台上运行基于Jupiter的测试。
JUnit Vintage提供了一个TestEngine,用于在平台上运行基于JUnit 3和JUnit 4的测试。
(通俗的讲,Junit是一个Java 单元测试框架。)
相关在线资料
官网主页
https://junit.org/junit5/
官网文档
https://junit.org/junit5/docs/current/user-guide/
GitHub - 项目源码
https://github.com/junit-team/junit5
GitHub - 示例源码
https://github.com/junit-team/junit5-samples
快速体验
引入依赖
JUnit需要Java8以上的运行环境。
Maven
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
Gradle
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.1')
}
SHOW ME THE CODE
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class HelloJunit5 {
@Test
void addition() {
assertEquals(2, 1+1);
}
}
标准测试类
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.*;
@DisplayName("一个标准的测试类")
public class StandardTest {
@BeforeAll
static void beforeAll() {
System.out.println("beforeAll");
}
@BeforeEach
void beforeEach() {
System.out.println("beforeEach");
}
@Test
@DisplayName("一个普通的测试方法")
void succeedingTest() {
System.out.println("succeedingTest");
}
@Test
@DisplayName("一个不普通的测试方法")
void failingTest() {
fail("a failing test");
}
@Test
@Disabled()
void skippedTest() {
System.out.println("skippedTest");
}
@AfterEach
void afterEach() {
System.out.println("afterEach");
}
@AfterAll
static void afterAll() {
System.out.println("afterAll");
}
}
运行结果:
beforeAll
beforeEach
succeedingTest
afterEach
beforeEach
afterEach
org.opentest4j.AssertionFailedError: a failing test
...此处省略大量栈信息
void StandardTest.skippedTest() is @Disabled
- 一个标准的生命周期如下
- beforeAll -> (beforeEach -> test -> afterEach) * @Test -> afterAll
- 使用@Disabled()可以跳过测试。
- @DisplayName,看上去优雅的注释方式。
断言 Assert
虽然org.junit.jupiter.api.Assertions满足了大部分场景,但是官方团队还是推荐开发者使用第三方断言类库,例如:AssertJ、Hamcrest、Truth 等等。
假设 Assumpt
org.junit.jupiter.api.Assumptions这个类非常微妙,我实在看不出有什么意义。
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assumptions.*;
import static org.junit.jupiter.api.Assertions.*;
public class AssumptionsTest {
@Test
@Disabled
public void assumeTrueT(){
//真没看出有啥区别
assumeTrue(false);
assertTrue(false);
}
@Test
public void test2(){
//我写if-else,它不香吗?
assumingThat(true,
() -> {
System.out.println("1");
});
}
}
附录
官方注解
被@Test、@TestTemplate、@RepeatedTest、@BeforeAll、@AfterAll、@BeforeEach 或 @AfterEach 注解标注的方法不可以有返回值。
@Test
表示该方法是一个测试方法。与JUnit 4的@Test注解不同的是,它没有声明任何属性,因为JUnit Jupiter中的测试扩展是基于它们自己的专用注解来完成的
@ParameterizedTest
表示该方法是一个参数化测试,value设置重复次数。
@RepeatedTest
表示该方法是一个重复测试的测试模板。
@TestFactory
表示该方法是一个 动态测试 的测试工厂。
@TestInstance
用于配置所标注的测试类的 测试实例生命周期。
@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方法(除非”per-class” 测试实例生命周期 被使用)
@AfterAll
表示使用了该注解的方法应该在当前类中所有使用了@Test、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之后执行;类似于JUnit 4的@AfterClass。这样的方法会被继承(除非它们被隐藏 或覆盖),并且它必须是 static方法(除非”per-class” 测试实例生命周期 被使用)。
@Nested
表示使用了该注解的类是一个内嵌、非静态的测试类。@BeforeAll和@AfterAll方法不能直接在@Nested测试类中使用,(除非”per-class” 测试实例生命周期 被使用)。
@Tag
用于声明过滤测试的tags,该注解可以用在方法或类上;类似于TesgNG的测试组或JUnit4的分类。该注解能被继承,但仅限于类级别,而非方法级别。
@Disable
用于禁用一个测试类或测试方法;类似于JUnit4的@Ignore。
@Timeout
如果其执行超过一个给定的持续时间,失败测试用例。
@ExtendWith
用于以申明方法注册自定义扩展。
@RegisterExtension
通过字段用于以编程方式注册自定义扩展。
@TempDir
用于提供一个临时目录通过字段注入或参数注入生命周期方法或试验方法;位于org.junit.jupiter.api.io包。
自定义注解
我们可以定义自己的组合注解,而自定义的组合注解会自动继承其元注解的语义。此处已官方Demo为例。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
public @interface FastTag {
}
通过这种方式,我们实现了一个与@Tag(“fast”)等价的自动定义注解@FastTag。