注解(Annotations)是JUnit的标志性技术,本文就来对它的20个注解,以及元注解和组合注解进行学习。

20个注解

org.junit.jupiter.api包中定义了这些注解,它们分别是:

  • @Test 测试方法,可以直接运行。

  • @ParameterizedTest 参数化测试,比如:

    @ParameterizedTest
    @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
    void palindromes(String candidate) {
    assertTrue(StringUtils.isPalindrome(candidate));
    }
  • @RepeatedTest 重复测试,比如:

    @RepeatedTest(10)
    void repeatedTest() {
    // ...
    }
  • @TestFactory 测试工厂,专门生成测试方法,比如:

    import org.junit.jupiter.api.DynamicTest;
    
    @TestFactory
    Collection<DynamicTest> dynamicTestsFromCollection() {
    return Arrays.asList(
    dynamicTest("1st dynamic test", () -> assertTrue(isPalindrome("madam"))),
    dynamicTest("2nd dynamic test", () -> assertEquals(4, calculator.multiply(2, 2)))
    );
    }
  • @TestTemplate 测试模板,比如:

    final List<String> fruits = Arrays.asList("apple", "banana", "lemon");
    
    @TestTemplate
    @ExtendWith(MyTestTemplateInvocationContextProvider.class)
    void testTemplate(String fruit) {
    assertTrue(fruits.contains(fruit));
    } public class MyTestTemplateInvocationContextProvider
    implements TestTemplateInvocationContextProvider { @Override
    public boolean supportsTestTemplate(ExtensionContext context) {
    return true;
    } @Override
    public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(
    ExtensionContext context) { return Stream.of(invocationContext("apple"), invocationContext("banana"));
    }
    }

    @TestTemplate必须注册一个TestTemplateInvocationContextProvider,它的用法跟@Test类似。

  • @TestMethodOrder 指定测试顺序,比如:

    import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
    import org.junit.jupiter.api.Order;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.TestMethodOrder; @TestMethodOrder(OrderAnnotation.class)
    class OrderedTestsDemo { @Test
    @Order(1)
    void nullValues() {
    // perform assertions against null values
    } @Test
    @Order(2)
    void emptyValues() {
    // perform assertions against empty values
    } @Test
    @Order(3)
    void validValues() {
    // perform assertions against valid values
    } }
  • @TestInstance 是否生成多个测试实例,默认JUnit每个测试方法生成一个实例,使用这个注解能让每个类只生成一个实例,比如:

    @TestInstance(Lifecycle.PER_CLASS)
    class TestMethodDemo { @Test
    void test1() {
    } @Test
    void test2() {
    } @Test
    void test3() {
    } }
  • @DisplayName 自定义测试名字,会体现在测试报告中,比如:

    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test; @DisplayName("A special test case")
    class DisplayNameDemo { @Test
    @DisplayName("Custom test name containing spaces")
    void testWithDisplayNameContainingSpaces() {
    } @Test
    @DisplayName("╯°□°)╯")
    void testWithDisplayNameContainingSpecialCharacters() {
    } @Test
    @DisplayName("")
    void testWithDisplayNameContainingEmoji() {
    } }
  • @DisplayNameGeneration 测试名字统一处理,比如:

    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.DisplayNameGeneration;
    import org.junit.jupiter.api.DisplayNameGenerator;
    import org.junit.jupiter.api.IndicativeSentencesGeneration;
    import org.junit.jupiter.api.Nested;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.ValueSource; class DisplayNameGeneratorDemo { @Nested
    @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    class A_year_is_not_supported { @Test
    void if_it_is_zero() {
    } @DisplayName("A negative value for year is not supported by the leap year computation.")
    @ParameterizedTest(name = "For example, year {0} is not supported.")
    @ValueSource(ints = { -1, -4 })
    void if_it_is_negative(int year) {
    } } @Nested
    @IndicativeSentencesGeneration(separator = " -> ", generator = DisplayNameGenerator.ReplaceUnderscores.class)
    class A_year_is_a_leap_year { @Test
    void if_it_is_divisible_by_4_but_not_by_100() {
    } @ParameterizedTest(name = "Year {0} is a leap year.")
    @ValueSource(ints = { 2016, 2020, 2048 })
    void if_it_is_one_of_the_following_years(int year) {
    } } }
  • @BeforeEach 在每个@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory之前执行。

  • @AfterEach 在每个@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory之后执行。

  • @BeforeAll所有的@Test, @RepeatedTest, @ParameterizedTest, and @TestFactory之前执行。

  • @AfterAll所有的@Test, @RepeatedTest, @ParameterizedTest, and @TestFactory之后执行。

  • @Nested 嵌套测试,一个类套一个类,例子参考上面那个。

  • @Tag 打标签,相当于分组,比如:

    import org.junit.jupiter.api.Tag;
    import org.junit.jupiter.api.Test; @Tag("fast")
    @Tag("model")
    class TaggingDemo { @Test
    @Tag("taxes")
    void testingTaxCalculation() {
    } }
  • @Disabled 禁用测试,比如:

    import org.junit.jupiter.api.Disabled;
    import org.junit.jupiter.api.Test; @Disabled("Disabled until bug #99 has been fixed")
    class DisabledClassDemo { @Test
    void testWillBeSkipped() {
    } }
  • @Timeout 对于test, test factory, test template, or lifecycle method,如果超时了就认为失败了,比如:

    class TimeoutDemo {
    
        @BeforeEach
    @Timeout(5)
    void setUp() {
    // fails if execution time exceeds 5 seconds
    } @Test
    @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    void failsIfExecutionTimeExceeds100Milliseconds() {
    // fails if execution time exceeds 100 milliseconds
    } }
  • @ExtendWith 注册扩展,比如:

    @ExtendWith(RandomParametersExtension.class)
    @Test
    void test(@Random int i) {
    // ...
    }

    JUnit5提供了标准的扩展机制来允许开发人员对JUnit5的功能进行增强。JUnit5提供了很多的标准扩展接口,第三方可以直接实现这些接口来提供自定义的行为。

  • @RegisterExtension 通过字段注册扩展,比如:

    class WebServerDemo {
    
        @RegisterExtension
    static WebServerExtension server = WebServerExtension.builder()
    .enableSecurity(false)
    .build(); @Test
    void getProductList() {
    WebClient webClient = new WebClient();
    String serverUrl = server.getServerUrl();
    // Use WebClient to connect to web server using serverUrl and verify response
    assertEquals(200, webClient.get(serverUrl + "/products").getResponseStatus());
    } }
  • @TempDir 临时目录,比如:

    @Test
    void writeItemsToFile(@TempDir Path tempDir) throws IOException {
    Path file = tempDir.resolve("test.txt"); new ListWriter(file).write("a", "b", "c"); assertEquals(singletonList("a,b,c"), Files.readAllLines(file));
    }

元注解和组合注解

JUnit Jupiter支持元注解,能继承后实现自定义注解,比如自定义@Fast注解:

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 Fast {
}

使用:

@Fast
@Test
void myFastTest() {
// ...
}

这个@Fast注解也是组合注解,甚至可以更进一步和@Test组合:

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;
import org.junit.jupiter.api.Test; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
@Test
public @interface FastTest {
}

只用@FastTest就可以了:

@FastTest
void myFastTest() {
// ...
}

小结

本文对JUnit20个主要的注解进行了介绍和示例演示,JUnit Jupiter支持元注解,可以自定义注解,也可以把多个注解组合起来。

参考资料:

https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

https://vitzhou.gitbooks.io/junit5/content/junit/extension_model.html#概述

JUnit5注解学习指引的更多相关文章

  1. 转-Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable

    转-http://snowolf.iteye.com/blog/1628861/ Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariab ...

  2. 【转】Spring 注解学习手札(超好的springmvc注解教程)

    Spring 注解学习手札(一) 构建简单Web应用 Spring 注解学习手札(二) 控制层梳理 Spring 注解学习手札(三) 表单页面处理 Spring 注解学习手札(四) 持久层浅析 Spr ...

  3. Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable (转)

    最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服! 相关参考: Spring 注解学习手札(一 ...

  4. Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable(转)

    最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服! 相关参考: Spring 注解学习手札(一 ...

  5. Spring @Autowired 注解 学习资料

    Spring @Autowired 注解 学习资料 网址 Spring @Autowired 注解 https://wiki.jikexueyuan.com/project/spring/annota ...

  6. 注解学习(模仿springMvc的注解注入方式)

    最近在看springMvc的源码,看到了该框架的注入注解的部分觉的有点吃力,可能还是对注解的方面的知识还认识的不够深刻,所以特意去学习注解方面的知识.由于本人也是抱着学习的态度来阅读源码,若文章在表述 ...

  7. spring mvc 注解 学习笔记(一)

    以前接触过spring,但是没有接触spring mvc 以及注解的应用,特习之,记之: 注解了解 @Component 是通用标注, @Controller 标注web控制器, @Service 标 ...

  8. Spring的IOC注解学习

    先引入jar包,common-annotations.jar 接着上代码: 1.dao接口 package com.dao; public interface OkpDao { public void ...

  9. Struts2注解学习1

    这是开博的第一篇,我希望每天把我学到的东西记录下来,成为一个知识库,方便以后的学习和分享 在项目中看到用struts2注解来做,很方便,做了一个用户登录的例子 1.加载所需jar包 commons-f ...

随机推荐

  1. CF1444A Division 求质因数的方法

    2020.12.20 求质因数的方法 CF1444A Division #include<bits/stdc++.h> #define ll long long #define fp(i, ...

  2. 使用gulp搭建项目

    项目源码地址 前期准备工作 首先确保本机安装了 node gulp中文文档 安装 gulp 命令行工具 npm install --global gulp-cli 在项目目录下创建 package.j ...

  3. [笔记] 《我的第一本c++书》

    函数 优秀函数的五个要点 函数的返回值:直接返回和间接返回(指针) 在函数的入口处对参数有效性进行检验:if语句,断言(assert) 如果函数有返回值,不可返回一个指向函数体内局部对象的指针或引用 ...

  4. Mysql数据库基础增删改查常用语句命令

    Mysql增删改查常用语句命令 一.增删改查语句总览 创建: create(创建数据库) 增:insert(插入表数据) 删:drop.delete(删除表.删除表数据) 改:update.alter ...

  5. Linux_配置主DNS服务(基础)

    [RHEL8]-DNSserver:[Centos7.4]-DNSclient !!!测试环境我们首关闭防火墙和selinux(DNSserver和DNSclient都需要) [root@localh ...

  6. 下面附上top和sar的使用方法,方便参考! "top"工具

    下面附上top和sar的使用方法,方便参考! "top"工具 使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b] 说明:即时显示 ...

  7. mysql基础之帮助信息

    在mysql中获取帮助 1.当连接到mysql数据库以后,使用help命令或者\?表示获取帮助信息: MariaDB [ren]> help General information about ...

  8. docker 部署应用

    Docker 部署应用 所需环境 Linux系统:centos7 (推荐7.4) Docker环境:V1.13.1 镜像:应用镜像包 docker部署和基本命令: 1. docker环境搭建 a)   ...

  9. python3 xlrd包的用法

    一.xlrd的安装 pip install xlrd 二.xlrd使用介绍 1.导入模块 import xlrd 2.打开Excel文件,实例化为readbook readbook = xlrd.op ...

  10. 技术干货 | 如何在 Library 中使用/依赖 mPaaS?

    使用场景 在使用 mPaaS 框架过程中,有时需要复用模块.复用时需要按照使用 Module 依赖的方式添加模块.本文以将复用 mPaaS 扫码组件的 Module 为例进行说明. 前提条件 已按照原 ...