JUnit5 快速指南

version: junit5

  • 1. 安装
  • 2. JUnit 注解
  • 3. 编写单元测试
    • 3.1. 基本的单元测试类和方法
    • 3.2. 定制测试类和方法的显示名称
    • 3.3. 断言(Assertions)
    • 3.4. 假想(Assumptions)
    • 3.5. 禁用
    • 3.6. 测试条件
    • 3.7. 嵌套测试
    • 3.8. 重复测试
    • 3.9. 参数化测试
  • 4. 引用和引申

1. 安装

在 pom 中添加依赖

<properties><junit.jupiter.version>5.3.2</junit.jupiter.version>
</properties><dependencies><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency>
</dependencies>

组件间依赖关系:

2. JUnit 注解

Annotation Description
@Test Denotes that a method is a test method. Unlike JUnit 4’s @Test annotation, this annotation does not declare any attributes, since test extensions in JUnit Jupiter operate based on their own dedicated annotations. Such methods are inherited unless they are overridden.
@ParameterizedTest Denotes that a method is a parameterized test. Such methods are inherited unless they are overridden.
@RepeatedTest Denotes that a method is a test template for a repeated test. Such methods are inherited unless they are overridden.
@TestFactory Denotes that a method is a test factory for dynamic tests. Such methods are inherited unless they are overridden.
@TestInstance Used to configure the test instance lifecycle for the annotated test class. Such annotations are inherited.
@TestTemplate Denotes that a method is a template for test cases designed to be invoked multiple times depending on the number of invocation contexts returned by the registered providers. Such methods are inherited unless they are overridden.
@DisplayName Declares a custom display name for the test class or test method. Such annotations are not inherited.
@BeforeEach Denotes that the annotated method should be executed before each @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @Before. Such methods are inherited unless they are overridden.
@AfterEach Denotes that the annotated method should be executed after each @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @After. Such methods are inherited unless they are overridden.
@BeforeAll Denotes that the annotated method should be executed before all @Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @BeforeClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used).
@AfterAll Denotes that the annotated method should be executed after all @Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @AfterClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used).
@Nested Denotes that the annotated class is a nested, non-static test class. @BeforeAll and @AfterAllmethods cannot be used directly in a @Nested test class unless the "per-class" test instance lifecycle is used. Such annotations are not inherited.
@Tag Used to declare tags for filtering tests, either at the class or method level; analogous to test groups in TestNG or Categories in JUnit 4. Such annotations are inherited at the class level but not at the method level.
@Disabled Used to disable a test class or test method; analogous to JUnit 4’s @Ignore. Such annotations are not inherited.
@ExtendWith Used to register custom extensions. Such annotations are inherited.

3. 编写单元测试

3.1. 基本的单元测试类和方法

import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;class Junit5StandardTests {private static final Logger LOGGER = LoggerFactory.getLogger(Junit5StandardTests.class);@BeforeAllstatic void beforeAll() {LOGGER.info("call beforeAll()");}@BeforeEachvoid beforeEach() {LOGGER.info("call beforeEach()");}@Testvoid succeedingTest() {LOGGER.info("call succeedingTest()");}@Testvoid failingTest() {LOGGER.info("call failingTest()");// fail("a failing test");}@Test@Disabled("for demonstration purposes")void skippedTest() {LOGGER.info("call skippedTest()");// not executed}@AfterEachvoid afterEach() {LOGGER.info("call afterEach()");}@AfterAllstatic void afterAll() {LOGGER.info("call afterAll()");}
}

3.2. 定制测试类和方法的显示名称

支持普通字符、特殊符号、emoji

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;@DisplayName("A special test case")
class JunitDisplayNameDemo {@Test@DisplayName("Custom test name containing spaces")void testWithDisplayNameContainingSpaces() { }@Test@DisplayName("╯°□°)╯")void testWithDisplayNameContainingSpecialCharacters() { }@Test@DisplayName("?")void testWithDisplayNameContainingEmoji() { }
}

3.3. 断言(Assertions)

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.*;class AssertionsDemo {private static Person person;@BeforeAllpublic static void beforeAll() {person = new Person("John", "Doe");}@Testvoid standardAssertions() {assertEquals(2, 2);assertEquals(4, 4, "The optional assertion message is now the last parameter.");assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "+ "to avoid constructing complex messages unnecessarily.");}@Testvoid groupedAssertions() {// In a grouped assertion all assertions are executed, and any// failures will be reported together.assertAll("person", () -> assertEquals("John", person.getFirstName()),() -> assertEquals("Doe", person.getLastName()));}@Testvoid 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("n")));}, () -> {// 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")));});}@Testvoid exceptionTesting() {Throwable exception = assertThrows(IllegalArgumentException.class, () -> {throw new IllegalArgumentException("a message");});assertEquals("a message", exception.getMessage());}@Testvoid timeoutNotExceeded() {// The following assertion succeeds.assertTimeout(ofMinutes(2), () -> {// Perform task that takes less than 2 minutes.});}@Testvoid timeoutNotExceededWithResult() {// The following assertion succeeds, and returns the supplied object.String actualResult = assertTimeout(ofMinutes(2), () -> {return "a result";});assertEquals("a result", actualResult);}@Testvoid timeoutNotExceededWithMethod() {// The following assertion invokes a method reference and returns an object.String actualGreeting = assertTimeout(ofMinutes(2), AssertionsDemo::greeting);assertEquals("Hello, World!", actualGreeting);}@Testvoid timeoutExceeded() {// The following assertion fails with an error message similar to:// execution exceeded timeout of 10 ms by 91 msassertTimeout(ofMillis(10), () -> {// Simulate task that takes more than 10 ms.Thread.sleep(100);});}@Testvoid timeoutExceededWithPreemptiveTermination() {// The following assertion fails with an error message similar to:// execution timed out after 10 msassertTimeoutPreemptively(ofMillis(10), () -> {// Simulate task that takes more than 10 ms.Thread.sleep(100);});}private static String greeting() {return "Hello, World!";}}

3.4. 假想(Assumptions)

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.jupiter.api.Assumptions.assumingThat;import org.junit.jupiter.api.Test;class AssumptionsDemo {@Testvoid testOnlyOnCiServer() {assumeTrue("CI".equals(System.getenv("ENV")));// remainder of test}@Testvoid testOnlyOnDeveloperWorkstation() {assumeTrue("DEV".equals(System.getenv("ENV")),() -> "Aborting test: not on developer workstation");// remainder of test}@Testvoid testInAllEnvironments() {assumingThat("CI".equals(System.getenv("ENV")),() -> {// perform these assertions only on the CI serverassertEquals(2, 2);});// perform these assertions in all environmentsassertEquals("a string", "a string");}}

3.5. 禁用

禁用单元测试类示例:

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;@Disabled
class DisabledClassDemo {@Testvoid testWillBeSkipped() {}
}

禁用单元测试方法示例:

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;class DisabledTestsDemo {@Disabled@Testvoid testWillBeSkipped() {}@Testvoid testWillBeExecuted() {}
}

3.6. 测试条件

操作系统条件

@Test
@EnabledOnOs(MAC)
void onlyOnMacOs() {// ...
}@TestOnMac
void testOnMac() {// ...
}@Test
@EnabledOnOs({ LINUX, MAC })
void onLinuxOrMac() {// ...
}@Test
@DisabledOnOs(WINDOWS)
void notOnWindows() {// ...
}@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Test
@EnabledOnOs(MAC)
@interface TestOnMac {
}

Java 运行时版本条件

@Test
@EnabledOnJre(JAVA_8)
void onlyOnJava8() {// ...
}@Test
@EnabledOnJre({ JAVA_9, JAVA_10 })
void onJava9Or10() {// ...
}@Test
@DisabledOnJre(JAVA_9)
void notOnJava9() {// ...
}

系统属性条件

@Test
@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
void onlyOn64BitArchitectures() {// ...
}@Test
@DisabledIfSystemProperty(named = "ci-server", matches = "true")
void notOnCiServer() {// ...
}

3.7. 嵌套测试

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;import java.util.EmptyStackException;
import java.util.Stack;import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;@DisplayName("A stack")
class TestingAStackDemo {Stack<Object> stack;@Test@DisplayName("is instantiated with new Stack()")void isInstantiatedWithNew() {new Stack<>();}@Nested@DisplayName("when new")class WhenNew {@BeforeEachvoid createNewStack() {stack = new Stack<>();}@Test@DisplayName("is empty")void isEmpty() {assertTrue(stack.isEmpty());}@Test@DisplayName("throws EmptyStackException when popped")void throwsExceptionWhenPopped() {assertThrows(EmptyStackException.class, () -> stack.pop());}@Test@DisplayName("throws EmptyStackException when peeked")void throwsExceptionWhenPeeked() {assertThrows(EmptyStackException.class, () -> stack.peek());}@Nested@DisplayName("after pushing an element")class AfterPushing {String anElement = "an element";@BeforeEachvoid pushAnElement() {stack.push(anElement);}@Test@DisplayName("it is no longer empty")void isNotEmpty() {assertFalse(stack.isEmpty());}@Test@DisplayName("returns the element when popped and is empty")void returnElementWhenPopped() {assertEquals(anElement, stack.pop());assertTrue(stack.isEmpty());}@Test@DisplayName("returns the element when peeked but remains not empty")void returnElementWhenPeeked() {assertEquals(anElement, stack.peek());assertFalse(stack.isEmpty());}}}
}

3.8. 重复测试

import static org.junit.jupiter.api.Assertions.assertEquals;import java.util.logging.Logger;import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.TestInfo;class RepeatedTestsDemo {private Logger logger = // ...@BeforeEachvoid beforeEach(TestInfo testInfo, RepetitionInfo repetitionInfo) {int currentRepetition = repetitionInfo.getCurrentRepetition();int totalRepetitions = repetitionInfo.getTotalRepetitions();String methodName = testInfo.getTestMethod().get().getName();logger.info(String.format("About to execute repetition %d of %d for %s", //currentRepetition, totalRepetitions, methodName));}@RepeatedTest(10)void repeatedTest() {// ...}@RepeatedTest(5)void repeatedTestWithRepetitionInfo(RepetitionInfo repetitionInfo) {assertEquals(5, repetitionInfo.getTotalRepetitions());}@RepeatedTest(value = 1, name = "{displayName} {currentRepetition}/{totalRepetitions}")@DisplayName("Repeat!")void customDisplayName(TestInfo testInfo) {assertEquals(testInfo.getDisplayName(), "Repeat! 1/1");}@RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME)@DisplayName("Details...")void customDisplayNameWithLongPattern(TestInfo testInfo) {assertEquals(testInfo.getDisplayName(), "Details... :: repetition 1 of 1");}@RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}")void repeatedTestInGerman() {// ...}}

3.9. 参数化测试

@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
void palindromes(String candidate) {assertTrue(isPalindrome(candidate));
}

4. 引用和引申

  • Github
  • 官方用户手册
  • Javadoc
  • 版本声明
  • 官方示例

转载于:https://www.cnblogs.com/jingmoxukong/p/10162245.html

JUnit5 快速指南相关推荐

  1. 《树莓派Python编程指南》—— 1.3 树莓派快速指南

    本节书摘来自华章计算机<树莓派Python编程指南>一书中的第1章,第1.3节,作者:(美) Alex Bradbury Ben Everard更多章节内容可以访问云栖社区"华章 ...

  2. react 快速上手开发_React中测试驱动开发的快速指南

    react 快速上手开发 by Michał Baranowski 通过MichałBaranowski React中测试驱动开发的快速指南 (A quick guide to test-driven ...

  3. 30岁找不到工作很绝望_计算机为绝望的新编码员工作方式的快速指南

    30岁找不到工作很绝望 by Danielle Ormshaw 丹妮尔·欧姆肖(Danielle Ormshaw) 计算机为绝望的新编码员工作方式的快速指南 (The quick guide to t ...

  4. 快速指南:在DevOps中实现持续交付

    [编者的话]时至今日,以几乎相同的步调实现开发与交付已经成为一种必需.本份快速指南将帮助大家弄了解持续交付概念中的那些"良方"与"毒药". [烧脑式Kubern ...

  5. spring_Spring Boot登录选项快速指南

    spring "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...

  6. oauth2_带有Spring Security的OAuth 2.0快速指南

    oauth2 "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...

  7. 2.17 Jupyter/ipython 笔记本的快速指南-深度学习-Stanford吴恩达教授

    ←上一篇 ↓↑ 下一篇→ 2.16 关于 Python Numpy 向量的说明 回到目录 2.18 Logistic 损失函数的解释 Jupyter/ipython 笔记本的快速指南 (Quick t ...

  8. python源码精要(9)-CPython内部原理快速指南(1)

    对于那些有兴趣了解更多关于CPython内部原理的人,这是一个快速指南.它提供了一个摘要的源代码结构,并包含对资源的引用. 对于Python模块,典型的布局是: • Lib/<module> ...

  9. wxWidgets:编写应用程序的快速指南

    wxWidgets:编写应用程序的快速指南 wxWidgets:编写应用程序的快速指南 wxWidgets:编写应用程序的快速指南 要设置 wxWidgets 应用程序,您需要派生一个wxApp类并覆 ...

最新文章

  1. Java 构造方法与成员方法的区别
  2. 什么才是真正的程序员?
  3. 《学习opencv》笔记——矩阵和图像处理——cvMinManLoc,cvMul,cvNot,cvNorm and cvNormalize...
  4. keytool安装tls证书_TLS使用指南(一):如何在Rancher 2.x中进行TLS终止?
  5. 显卡在电脑什么位置_DIY组装电脑教程,新手也能学会自己组装电脑
  6. iOS经典面试题之“runtime是如何实现weak变量的自动置nil”
  7. 一个“alert” 引发的血案
  8. c++已知2点求中垂线_电力系统负荷预测-基本方法以及分析(2)
  9. WinAPI: CreatePen - 建立画笔
  10. 分析wordpress搭建的网站百度收录不好的原因
  11. h5 右下角浮动按钮_基于javascript实现右下角浮动广告效果
  12. android打印机字体大小,打印自定义文档  |  Android 开发者  |  Android Developers
  13. S7-1200 PLC的常见扩展模块
  14. 论文复现_芯片定位和引脚缺陷检测
  15. 小学计算机教师应聘简历,应聘小学教师的个人简历模板
  16. 使用git时代码被冲掉
  17. SVN打标签方法及在此过程中的问题处理
  18. 计算机主机制造过程,电脑宣传片的制作流程
  19. 3款Mac上相见恨晚的软件
  20. TCP旁路劫持,糟糕的RFC5961

热门文章

  1. 压缩命令tar cf xx.tar -C的正确用法
  2. IO对象不可以复制或者赋值
  3. 使用变量_在 Linux 中使用变量 | Linux 中国
  4. Shell——流程控制(if、case、for、while)
  5. 关于android的外文论文,关于android的外文文献.doc
  6. 树莓派c语言led,用树莓派实现RGB LED的颜色控制——C语言版本号
  7. Android-NDK-audio-echo
  8. mysql b tree图_MySQL索引--B-Tree(B+Tree)图文详解
  9. html rotate()函数,CSS rotate()用法及代码示例
  10. 5G NR 随机接入过程(1)