JUnit5

安卓build.gradle

https://github.com/mannodermaus/android-junit5

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()

它断言期望的字符串列表与实际列表相匹配。 将一个字符串与另一个字符串匹配的逻辑是:

  1. 检查expected.equals(actual) –如果是,则继续下一对
  2. 否则将expected视为正则表达式,并通过

    String.matches(String)检查–如果是,则继续下一对
  3. 否则检查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的更多相关文章

  1. JUnit5 安装与使用

    虽然JUnit5 的测试版本早就出来了,但正式版直到几年9月份推出,目前最新版5.0.1.几乎所有的Java 开发人员都会使用JUnit 来做测试,但其实很多自动化测试人员也会使用Junit .目前, ...

  2. JUnit5 技术前瞻

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6868495.html   JUnit ...

  3. JUnit5 快速指南

    JUnit5 快速指南 version: junit5 1. 安装 2. JUnit 注解 3. 编写单元测试 3.1. 基本的单元测试类和方法 3.2. 定制测试类和方法的显示名称 3.3. 断言( ...

  4. 单元测试系列之六:JUnit5 技术前瞻

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6868495.html   JUnit ...

  5. junit5了解一下

    要求java8及以上版本 JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage https://junit.org/junit5/docs/ ...

  6. junit5荟萃知识点(一):junit5的组成及安装

    1.什么是junit5? 和之前的junit版本不一样,junit5是由三个模块组成. JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage ...

  7. Java Junit5 Annotations

    @BeforeEach 在方法上注解,在每个测试方法运行之前执行 @AfterEach 在方法上注解,在每个测试方法运行之后执行 @BeforeAll 该注解方法会在所有测试方法之前运行,该方法必须是 ...

  8. 单元测试实践(SpringCloud+Junit5+Mockito+DataMocker)

    网上看过一句话,单元测试就像早睡早起,每个人都说好,但是很少有人做到.从这么多年的项目经历亲身证明,是真的. 这次借着项目内实施单元测试的机会,记录实施的过程和一些总结经验. 项目情况 首先是背景,项 ...

  9. Junit5中实现参数化测试

    从Junit5开始,对参数化测试支持进行了大幅度的改进和提升.下面我们就一起来详细看看Junit5参数化测试的方法. 部署和依赖 和Junit4相比,Junit5框架更多在向测试平台演进.其核心组成也 ...

  10. Idea 运行测试NoSuchMethodError Junit5

    1.背景 环境: macOS 10.13.4 idea: 2016.3 springboot 版本: 2.2.2.RELEASE pom依赖 <dependencies> <depe ...

随机推荐

  1. Apache DolphinScheduler 3.0.6 发布,或将是最后一个 3.0.X 版本

    Apache DolphinScheduler 于近日发布了 3.0.6 版本,主要针对 3.0.5 重要 bug 进行修复.如果之后没有发现重大问题,3.0.6 将会是 3.0.x 最后一个版本. ...

  2. SMU Summer 2023 Contest Round 8(2019 陕西省大学生程序设计竞赛)

    SMU Summer 2023 Contest Round 8(2019 陕西省大学生程序设计竞赛) B - Grid with Arrows(欧拉图) 题意:一个总规模为\(n × m\)的矩阵,矩 ...

  3. 精美的Vue3流程插件,欢迎使用。

    dawn-flow 插件是博主使用Vue3自主封装的流程插件(持续迭代中). 截图: dawn-flow 采用拖拽方式创建流程. dawn-flow,开放了2个属性和2个事件,具体如下: 属性 Nod ...

  4. 初三年后集训测试---T1排序

    初三年后集训测试 $T 1 $ 排序 $$HZOI$$ ·题意: 给定 \(4n\) 个整数,求 : \[\max\{\sum_{i=1}^{4n}(A_{i,1} \times A_{i,2} - ...

  5. 玄机蓝队靶场_应急响应_02:apache日志分析

    日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...

  6. Ansible-playbook 应用梳理

    前面已经介绍过Ansible的安装配置及常见模块的使用 --<Linux下使用Ansible处理批量操作> Palybook简介 palybook是由一个或多个paly组成的列表,play ...

  7. P 问题和 NP 问题的简单理解

    P/NP问题 | 维基百科 P 问题 P 问题的定义是:所有可以由一个确定型图灵机在多项式表达的时间内解决的问题 P 代表 Polynomial-time (adj. 多项式时间) 简单理解:答案可以 ...

  8. 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 产生这种条件的原因一般是使用 ...

  9. 小tips:HTML的实体

    为了能在HTML文档中正确显示某些特殊字符,就需要使用HTML实体(entity).HTML实体就是对当前文档的编码方式不能包含的字符,提供一种转义表示. HTML实体定义 1.名称方式 名称方式会以 ...

  10. Entity Framework Plus: 让 EF Core 开发如虎添翼

    EF Core介绍 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台版的常用 Entity Framework 数据访问技术,EF Core 是适用于 .NET 的 ...