Junit5
JUnit5
安卓build.gradle
Unit 3 或 JUnit4 的向后兼容性
JUnit4 已经存在了很长时间,并且用 JUnit4 编写了许多测试。JUnitJupiter 也需要支持这些测试。 为此,开发了 JUnit Vintage 子项目。
JUnit Vintage 提供了
TestEngine实现,用于在 JUnit5 平台上运行基于 JUnit 3 和 JUnit4 的测试。
注解
- 所有核心注解位于
junit-jupiter-api模块中的org.junit.jupiter.api包中。 - 测试类和测试方法都不必是
public。
| 注解 | 描述 |
|---|---|
| @Test | 表示方法是测试方法。与JUnit4的@Test注解不同的是,这个注解没有声明任何属性,因为JUnit Jupiter中的测试扩展是基于他们自己的专用注解来操作的。除非被覆盖,否则这些方法可以继承。 |
| @ParameterizedTest | 表示方法是参数化测试。 除非被覆盖,否则这些方法可以继承。 |
| @RepeatedTest | 表示方法是用于重复测试的测试模板。除非被覆盖,否则这些方法可以继承。 |
| @TestFactory | 表示方法是用于动态测试的测试工厂。除非被覆盖,否则这些方法可以继承。 |
| @TestInstance | 用于为被注解的测试类配置测试实例生命周期。 这个注解可以继承。 |
| @TestTemplate | 表示方法是测试用例的模板,设计为被调用多次,调用次数取决于自注册的提供者返回的调用上下文。除非被覆盖,否则这些方法可以继承。 |
| @DisplayName | 声明测试类或测试方法的自定义显示名称。这个注解不被继承。 |
| @BeforeEach | 表示被注解的方法应在当前类的每个@Test,@RepeatedTest,@ParameterizedTest或@TestFactory方法之前执行; 类似于JUnit 4的@Before。 除非被覆盖,否则这些方法可以继承。 |
| @AfterEach | 表示被注解的方法应在当前类的每个@Test,@RepeatedTest,@ParameterizedTest或@TestFactory方法之后执行; 类似于JUnit 4的@After。 除非被覆盖,否则这些方法可以继承。 |
| @BeforeAll | 表示被注解的方法应该在当前类的所有@Test,@RepeatedTest,@ParameterizedTest和@TestFactory方法之前执行; 类似于JUnit 4的@BeforeClass。 这样的方法可以继承(除非被隐藏或覆盖),并且必须是静态的(除非使用“per-class”测试实例生命周期)。 |
| @AfterAll | 表示被注解的方法应该在当前类的所有@Test,@RepeatedTest,@ParameterizedTest和@TestFactory方法之后执行; 类似于JUnit 4的@AfterClass。 这样的方法可以继承(除非被隐藏或覆盖),并且必须是静态的(除非使用“per-class”测试实例生命周期)。 |
| @Nested | 表示被注解的类是一个嵌套的非静态测试类。除非使用“per-class”测试实例生命周期,否则@BeforeAll和@AfterAll方法不能直接在@Nested测试类中使用。 这个注解不能继承。 |
| @Tag | 在类或方法级别声明标签,用于过滤测试; 类似于TestNG中的test group或JUnit 4中的Categories。这个注释可以在类级别上继承,但不能在方法级别上继承。 |
| @Disabled | 用于禁用测试类或测试方法; 类似于JUnit4的@Ignore。这个注解不能继承。 |
| @ExtendWith | 用于注册自定义扩展。 这个注解可以继承。 |
- 简单的注解使用
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.*;
class FirstJUnit5Tests {
/**
* 只会执行一次
* 必须为static
*/
@BeforeAll
static void beforeAll(){
System.out.println("before all");
}
@AfterAll
static void afterAll(){
System.out.println("after all");
}
/**
* 在每个测试单元执行前都会执行一次
*/
@BeforeEach
void beforeEach(){
System.out.println("before each");
}
@AfterEach
void afterEach(){
System.out.println("after each");
}
@DisplayName("测试一")
@Test
void test1() {
assertEquals(2, 2, "error");
}
/**
* 禁用测试方法,也可以禁用测试类
*/
@Disabled
@Test
void test2(){
System.out.println(2);
}
}
- @RepeatedTest
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.*;
class FirstJUnit5Tests {
@BeforeEach
void beforeEach(RepetitionInfo info){
int currentRepetition = info.getCurrentRepetition();
int totalRepetition = info.getTotalRepetitions();
System.out.println("before each " + currentRepetition + "/" + totalRepetition);
}
@AfterEach
void afterEach(RepetitionInfo info){
int currentRepetition = info.getCurrentRepetition();
int totalRepetition = info.getTotalRepetitions();
System.out.println("after each " + currentRepetition + "/" + totalRepetition);
}
@DisplayName("测试三")
// @RepeatedTest(value = 3, name = "{displayName} - repetition {currentRepetition} of {totalRepetitions}")
// @RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)
@RepeatedTest(value = 3) // 默认的SHORT_DISPLAY_NAME
void test3(){
System.out.println("test3 executed");
}
}

- @Tag
@Tag("tagA")
@Test
void test1(){
System.out.println("test1");
}
@Tag("tagA")
@Tag("tagC")
@Test
void test2(){
System.out.println("test2");
}
@Tag("tagB")
@Tag("tagC")
@DisplayName("测试三")
@RepeatedTest(value = 3)
void test3(){
System.out.println("test3 executed");
}
断言
- 所有方法
Assertions.assertEquals() and Assertions.assertNotEquals()
Assertions.assertArrayEquals()
Assertions.assertIterableEquals()
Assertions.assertLinesMatch()
Assertions.assertNotNull() and Assertions.assertNull()
Assertions.assertNotSame() and Assertions.assertSame()
Assertions.assertTimeout() and Assertions.assertTimeoutPreemptively()
Assertions.assertTrue() and Assertions.assertFalse()
Assertions.assertThrows()
Assertions.fail()
Assertions.assertEquals()
/**
* assertEquals()针对不同的数据类型
* 还支持传递传递的错误消息
*/
@Test
void test1() {
System.out.println("test1");
// pass
Assertions.assertEquals(4, 4);
// fail
Assertions.assertEquals(3, 4, "Calculator.add(2, 2) test failed");
// fail
Supplier<String> messageSupplier = () -> "Calculator.add(2, 2) test failed";
Assertions.assertEquals(3, 4, messageSupplier);
}
/**
* assertNotEquals()不会针对不同的数据类型重载方法,而仅接受Object
* public static void assertNotEquals(Object expected, Object actual)
* public static void assertNotEquals(Object expected, Object actual, String message)
* public static void assertNotEquals(Object expected, Object actual, Supplier<String> messageSupplier)
*/
@Test
void test2() {
Assertions.assertNotEquals(3, 4);
}
- 判断Object是否相等的源码
static void assertEquals(Object expected, Object actual, String message) {
if (!AssertionUtils.objectsAreEqual(expected, actual)) {
AssertionUtils.failNotEqual(expected, actual, message);
}
}
/**
* 对于 ==
* 基本类型:比较的是值是否相同;
* 引用类型:比较的是引用是否相同;
* 对于 equals
* 本质上就是 ==
* 只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较
*/
static boolean objectsAreEqual(Object obj1, Object obj2) {
if (obj1 == null) {
return obj2 == null;
} else {
return obj1.equals(obj2);
}
}
Assertions.assertArrayEquals()
@Test
void test1() {
//Test will pass
Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,2,3}, "Array Equal Test");
//Test will fail because element order is different
Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,3,2}, "Array Equal Test");
//Test will fail because number of elements are different
Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,2,3,4}, "Array Equal Test");
}
Assertions.assertIterableEquals()
/**
* 断言期望和实际的可迭代项高度相等。
* 高度相等意味着集合中元素的数量和顺序必须相同; 以及迭代元素必须相等。
*/
@Test
void test1() {
Iterable<Integer> listOne = new ArrayList<>(Arrays.asList(1,2,3,4));
Iterable<Integer> listTwo = new ArrayList<>(Arrays.asList(1,2,3,4));
Iterable<Integer> listThree = new ArrayList<>(Arrays.asList(1,2,3));
Iterable<Integer> listFour = new ArrayList<>(Arrays.asList(1,2,4,3));
//Test will pass
Assertions.assertIterableEquals(listOne, listTwo);
//Test will fail
Assertions.assertIterableEquals(listOne, listThree);
//Test will fail
Assertions.assertIterableEquals(listOne, listFour);
}
Assertions.assertLinesMatch()
它断言期望的字符串列表与实际列表相匹配。 将一个字符串与另一个字符串匹配的逻辑是:
- 检查
expected.equals(actual)–如果是,则继续下一对 - 否则将
expected视为正则表达式,并通过
String.matches(String)检查–如果是,则继续下一对 - 否则检查
expected行是否为快进标记,如果是,则相应地应用
快速前行并转到 1。
有效的快进标记是以>>开头和结尾并且至少包含 4 个字符的字符串。 快进文字之间的任何字符都将被丢弃。
>>>>
>> stacktrace >>
>> single line, non Integer.parse()-able comment >>
Assertions.assertNotNull()
@Test
void test1() {
String nullString = null;
String notNullString = "haha";
//Test will pass
Assertions.assertNotNull(notNullString);
//Test will fail
Assertions.assertNotNull(nullString);
//Test will pass
Assertions.assertNull(nullString);
// Test will fail
Assertions.assertNull(notNullString);
}
Assertions.assertNotSame()
assertNotSame()断言预期和实际不引用同一对象。 同样,assertSame()方法断言,预期和实际引用完全相同的对象
@Test
void test1() {
// 都是在常量池中取值,二者都指向常量池中同一对象,其地址值相同
String originalObject = "haha";
String cloneObject = originalObject;
String otherObject = "haha";
// 还是从常量池中取
String otherObject2 = new String(new char[]{'h', 'a','h', 'a'});
//Test will pass
Assertions.assertNotSame(originalObject, "hehe");
//Test will fail
Assertions.assertNotSame(originalObject, cloneObject);
//Test will pass
Assertions.assertSame(originalObject, cloneObject);
// Test will fail
Assertions.assertSame(originalObject, "hehe");
}
String为什么不用new:https://www.debugease.com/j2se/3709966.html
Assertions.assertTimeout()
/**
* 如果超过超时,Executable或ThrowingSupplier的执行将被抢先中止。
* 在assertTimeout()的情况下,不会中断Executable或ThrowingSupplier。
*/
@Test
void test1() {
//This will pass
Assertions.assertTimeout(Duration.ofMinutes(1), () -> "result");
//This will fail
Assertions.assertTimeout(Duration.ofMillis(100), () -> {
Thread.sleep(200);
return "result";
});
//This will fail
Assertions.assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
Thread.sleep(200);
return "result";
});
}
Assertions.assertTrue()
@Test
void testCase() {
boolean trueBool = true;
boolean falseBool = false;
Assertions.assertTrue(trueBool);
Assertions.assertTrue(falseBool, "test execution message");
Assertions.assertTrue(falseBool, FirstJUnit5Tests::message);
Assertions.assertTrue(FirstJUnit5Tests::getResult, FirstJUnit5Tests::message);
}
private static String message() {
return "Test execution result";
}
private static boolean getResult() {
return false;
}
Assertions.assertThrows()
/**
* 预期异常
*/
@Test
void testExpectedException() {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt("One");
});
}
/**
* 预期异常的超类
*/
@Test
void testExpectedExceptionWithSuperType() {
Assertions.assertThrows(IllegalArgumentException.class, () -> {
Integer.parseInt("One");
});
}
/**
* 抛出其他异常或者没有异常将会测试失败
*/
@Test
void testExpectedExceptionFail() {
Assertions.assertThrows(IllegalArgumentException.class, () -> {
Integer.parseInt("1");
});
}
Assertions.fail()
- 仅使测试失败
public static void fail(String message)
public static void fail(Throwable cause)
public static void fail(String message, Throwable cause)
public static void fail(Supplier<String> messageSupplier)
假设
Assumptions.assumeTrue()
@Test
void testOnDev() {
Assumptions.assumeTrue(true);
// 剩余的测试将继续
System.out.println("haha");
}
@Test
void testOnProd() {
Assumptions.assumeTrue(false, FirstJUnit5Tests::message);
// 剩余的测试将被中止
System.out.println("xixi");
}
private static String message() {
return "TEST Execution Failed :: ";
}
Junit5的更多相关文章
- JUnit5 安装与使用
虽然JUnit5 的测试版本早就出来了,但正式版直到几年9月份推出,目前最新版5.0.1.几乎所有的Java 开发人员都会使用JUnit 来做测试,但其实很多自动化测试人员也会使用Junit .目前, ...
- JUnit5 技术前瞻
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6868495.html JUnit ...
- JUnit5 快速指南
JUnit5 快速指南 version: junit5 1. 安装 2. JUnit 注解 3. 编写单元测试 3.1. 基本的单元测试类和方法 3.2. 定制测试类和方法的显示名称 3.3. 断言( ...
- 单元测试系列之六:JUnit5 技术前瞻
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6868495.html JUnit ...
- junit5了解一下
要求java8及以上版本 JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage https://junit.org/junit5/docs/ ...
- junit5荟萃知识点(一):junit5的组成及安装
1.什么是junit5? 和之前的junit版本不一样,junit5是由三个模块组成. JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage ...
- Java Junit5 Annotations
@BeforeEach 在方法上注解,在每个测试方法运行之前执行 @AfterEach 在方法上注解,在每个测试方法运行之后执行 @BeforeAll 该注解方法会在所有测试方法之前运行,该方法必须是 ...
- 单元测试实践(SpringCloud+Junit5+Mockito+DataMocker)
网上看过一句话,单元测试就像早睡早起,每个人都说好,但是很少有人做到.从这么多年的项目经历亲身证明,是真的. 这次借着项目内实施单元测试的机会,记录实施的过程和一些总结经验. 项目情况 首先是背景,项 ...
- Junit5中实现参数化测试
从Junit5开始,对参数化测试支持进行了大幅度的改进和提升.下面我们就一起来详细看看Junit5参数化测试的方法. 部署和依赖 和Junit4相比,Junit5框架更多在向测试平台演进.其核心组成也 ...
- Idea 运行测试NoSuchMethodError Junit5
1.背景 环境: macOS 10.13.4 idea: 2016.3 springboot 版本: 2.2.2.RELEASE pom依赖 <dependencies> <depe ...
随机推荐
- Apache DolphinScheduler 3.0.6 发布,或将是最后一个 3.0.X 版本
Apache DolphinScheduler 于近日发布了 3.0.6 版本,主要针对 3.0.5 重要 bug 进行修复.如果之后没有发现重大问题,3.0.6 将会是 3.0.x 最后一个版本. ...
- SMU Summer 2023 Contest Round 8(2019 陕西省大学生程序设计竞赛)
SMU Summer 2023 Contest Round 8(2019 陕西省大学生程序设计竞赛) B - Grid with Arrows(欧拉图) 题意:一个总规模为\(n × m\)的矩阵,矩 ...
- 精美的Vue3流程插件,欢迎使用。
dawn-flow 插件是博主使用Vue3自主封装的流程插件(持续迭代中). 截图: dawn-flow 采用拖拽方式创建流程. dawn-flow,开放了2个属性和2个事件,具体如下: 属性 Nod ...
- 初三年后集训测试---T1排序
初三年后集训测试 $T 1 $ 排序 $$HZOI$$ ·题意: 给定 \(4n\) 个整数,求 : \[\max\{\sum_{i=1}^{4n}(A_{i,1} \times A_{i,2} - ...
- 玄机蓝队靶场_应急响应_02:apache日志分析
日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...
- Ansible-playbook 应用梳理
前面已经介绍过Ansible的安装配置及常见模块的使用 --<Linux下使用Ansible处理批量操作> Palybook简介 palybook是由一个或多个paly组成的列表,play ...
- P 问题和 NP 问题的简单理解
P/NP问题 | 维基百科 P 问题 P 问题的定义是:所有可以由一个确定型图灵机在多项式表达的时间内解决的问题 P 代表 Polynomial-time (adj. 多项式时间) 简单理解:答案可以 ...
- Failed to convert value of type 'java.lang.String' to required type
DEBUG 微信小程序Java后台 Failed to convert value of type 'java.lang.String' to required type 产生这种条件的原因一般是使用 ...
- 小tips:HTML的实体
为了能在HTML文档中正确显示某些特殊字符,就需要使用HTML实体(entity).HTML实体就是对当前文档的编码方式不能包含的字符,提供一种转义表示. HTML实体定义 1.名称方式 名称方式会以 ...
- Entity Framework Plus: 让 EF Core 开发如虎添翼
EF Core介绍 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台版的常用 Entity Framework 数据访问技术,EF Core 是适用于 .NET 的 ...