注解(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. 剑指offer 数组中的重复数字

    问题描述: 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1 ...

  2. makefile的include用法

    include 使用方法 : include filename.mk 作用: 暂停当前的makefile执行,去执行指定的makefile,执行完毕后继续执行当前的makefile -include ...

  3. [刷题] PTA 6-10 阶乘计算升级版

    要求: 实现一个打印非负整数阶乘的函数 N是用户传入的参数,其值不超过1000.如果N是非负整数,则该函数必须在一行中打印出N!的值,否则打印"Invalid input" 1 # ...

  4. 攻防世界(五)Web_php_include

    攻防世界系列:Web_php_include 方法一:大小写绕过 strstr()函数对php我协议进行了过滤,但我们可以尝试大小写绕过 抓包POST传值让其执行我们输入的命令 ?page=Php:/ ...

  5. 014.Python函数

    一 函数的概念 1.1 函数的含义 功能 (包裹一部分代码 实现某一个功能 达成某一个目的) 1.2 函数特点 可以反复调用,提高代码的复用性,提高开发效率,便于维护管理 1.3 函数的基本格式 # ...

  6. MyBatis 动态 SQL 语句中出现 '<' 的问题

    问题描述 映射接口方法如下: /** * 根据姓名和年龄查询用户信息 * @param name 姓名 * @param user 获取年龄 * @return */ public List<U ...

  7. 什么是FOC

    https://zhidao.baidu.com/question/354536332.html FOC简述 磁场定向控制系统(FOC)又称为矢量控制系统,他是选择电机某一旋转磁场轴作为特定的同步旋转 ...

  8. 使用Selenium从IEEE与谷歌学术批量爬取BibTex文献引用

    搞科研的小伙伴总是会被期刊严苛的引用文献格式搞的很头疼.虽然常用的文献软件可以一键导出BibTex,但由于很多论文在投稿之前都会先发上Arxiv占坑,软件就很可能会把文献引出为来自Arxiv.我用的是 ...

  9. unity texture 占用内存大小对比

    打包多种类型的项目,空项目和10张放在Resources文件夹中的图为比较案例.以下是比较数据. IPHONE: 1.空项目----空间占用量42.3MB----IPA大小10MB 2.10张1200 ...

  10. Question&&Answer

    1.使用Navicat连接Ubuntu上面的MySql数据库失败 解决办法:Navicat版本的问题,尝试换用更高版本的Navicat解决了问题(当时使用了Navicat Premium_11.2.7 ...