注解(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. 手写Spring MVC框架(二) 实现访问拦截功能

    前言 在上一篇文章中,我们手写了一个简单的mvc框架,今天我们要实现的功能点是:在Spring MVC框架基础上实现访问拦截功能. 先梳理一下需要实现的功能点: 搭建好Spring MVC基本框架: ...

  2. slickgrid ( nsunleo-slickgrid ) 8 区域选择与复制粘贴

    区域选择 区域选择是通过插件CellRangeSelector实现的,默认不支持跨冻结列进行选择,修正了选择,支持跨冻结列,代码如下,通过判断选择的起点和终点所落在的冻结范围进行计算,如从左往右进行复 ...

  3. PostgreSQL条件表达式

      条件表达式在日常工作中很多场景都会用到,比如某个字段为空,取另外一个字段:某个值大于多少,取什么字段,小于多少取什么字段等等.那么下面来简单的学习下PostgreSQL有那些条件表达式. 1.CA ...

  4. 使用U盘软碟通安装原版Windows10

    https://zhuanlan.zhihu.com/p/171534675 使用U盘软碟通安装原版Windows10 一.准备:8G U盘一个,电脑装好UltraISO这个软件下载地址 二.Wind ...

  5. 在Vim中查看文件编码和文件编码转换

    在Vim中查看文件编码和文件编码转换 风亡小窝 关注  0.2 2016.09.26 22:43* 字数 244 阅读 5663评论 0喜欢 2 在Vim中查看文件编码 :set fileencodi ...

  6. Docker创建镜像以及私有仓库

    Docker的安装及镜像.容器的基本操作详见博客https://blog.51cto.com/11134648/2160257下面介绍Docker创建镜像和创建私有仓库的方法,详细如下: 创建镜像 创 ...

  7. centos7基于luks对磁盘进行加密

    centos7基于luks对磁盘进行加密 1,504 views A+ 所属分类:linux 收  藏 LUKS(Linux Unified Key Setup)为Linux硬盘加密提供了一种标准,它 ...

  8. mysql基础之mariadb概念

    一.数据库介绍 什么是数据库(Database)? 简单的说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构(数据结构是指数据的组织形式或数据之间的联系)来组织,存储的,我们可以通过数据库 ...

  9. Centos 重置root密码

    # cat /etc/system-release                         #查看版本 开机后在内核grub.2上敲击 e 在linux16 行(倒数第二行)末加入 " ...

  10. jq slideDown后里面的A链接失效(已解决)

    jq slideDown后里面的A链接失效(解决) 用jq 的 slideDown写了一个二级下拉菜单,但是里面的a标签全部失效了,挂的链接右键菜单可以正常打开,但是左键正常点击不行 查阅了很多资料, ...