JUnit5注解学习指引
注解(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注解学习指引的更多相关文章
- 转-Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable
转-http://snowolf.iteye.com/blog/1628861/ Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariab ...
- 【转】Spring 注解学习手札(超好的springmvc注解教程)
Spring 注解学习手札(一) 构建简单Web应用 Spring 注解学习手札(二) 控制层梳理 Spring 注解学习手札(三) 表单页面处理 Spring 注解学习手札(四) 持久层浅析 Spr ...
- Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable (转)
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服! 相关参考: Spring 注解学习手札(一 ...
- Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable(转)
最近需要做些接口服务,服务协议定为JSON,为了整合在Spring中,一开始确实费了很大的劲,经朋友提醒才发现,SpringMVC已经强悍到如此地步,佩服! 相关参考: Spring 注解学习手札(一 ...
- Spring @Autowired 注解 学习资料
Spring @Autowired 注解 学习资料 网址 Spring @Autowired 注解 https://wiki.jikexueyuan.com/project/spring/annota ...
- 注解学习(模仿springMvc的注解注入方式)
最近在看springMvc的源码,看到了该框架的注入注解的部分觉的有点吃力,可能还是对注解的方面的知识还认识的不够深刻,所以特意去学习注解方面的知识.由于本人也是抱着学习的态度来阅读源码,若文章在表述 ...
- spring mvc 注解 学习笔记(一)
以前接触过spring,但是没有接触spring mvc 以及注解的应用,特习之,记之: 注解了解 @Component 是通用标注, @Controller 标注web控制器, @Service 标 ...
- Spring的IOC注解学习
先引入jar包,common-annotations.jar 接着上代码: 1.dao接口 package com.dao; public interface OkpDao { public void ...
- Struts2注解学习1
这是开博的第一篇,我希望每天把我学到的东西记录下来,成为一个知识库,方便以后的学习和分享 在项目中看到用struts2注解来做,很方便,做了一个用户登录的例子 1.加载所需jar包 commons-f ...
随机推荐
- docker-compose如何动态配置springboot项目的application.yml的配置
假如我们再springboot的工程中有配置文件 方式1: application.properties里面存在环境变量: #配置数据库链接 spring.datasource.url = jdbc: ...
- [DB] Spark Core (1)
生态 Spark Core:最重要,其中最重要的是RDD(弹性分布式数据集) Spark SQL Spark Streaming Spark MLLib:机器学习算法 Spark Graphx:图计算 ...
- [Qt] 事件机制(二)
在samp4_1中加一个小功能,点击右上角关闭按钮时,弹出"确认是否关闭"的消息框.如果点"yes"则关闭,如果点"No"则不关闭 在wid ...
- g77介绍 g77 是 Fortran77 的编译器。它对 Fortran 77 标准提供完备的支持,并支持 Fortran 90 和 95 的部分特性。 由于 Fortran 77 标准在数值计算中的影响力,g77 可能是应用最广的Fortran编译器。 在 GCC 4.0 之前,g77 是 GCC 的一部分,但现在,g77 已经停止开发。
GFORTRAN 维基百科,自由的百科全书 跳到导航 跳到搜索 此条目需要扩充. (2018年11月2日)请协助改善这篇条目,更进一步的信息可能会在讨论页或扩充请求中找到.请在扩充条目后将此模 ...
- Installing SFTP/SSH Server on Windows using OpenSSH
Installing SFTP/SSH Server 1. On Windows 10 version 1803 and newer In Settings app, go to Apps > ...
- windows怎么访问linux的samba共享目录
windows怎么访问linux的samba共享目录 听语音 原创 | 浏览:6976 | 更新:2018-07-31 13:20 | 标签:LINUX WINDOWS 1 2 3 4 5 6 7 分 ...
- SSH 远程控制
本文以 Ubuntu 20.04(客户端) 控制 Kali Linux 2020.2(服务端)为例 1.安装SSH(secure Shell) SSH分为客户端oppenssh-client和服务端o ...
- xshell中登录服务器图形化界面
安装全套的xmanager程序 打开xshell工具程序 点击新建 输入ip等必要信息 点击隧道,英文版为tunnel 勾选红色的选项1和2 填写一些用户名和密码信息(图就略了O(∩_∩)O) 敲入指 ...
- Go语言实现Snowflake雪花算法
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/527 每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这 ...
- Django 自定义表名和字段名
Django 自定义表名和字段名 通过db_table和db_column自定义数据表名和字段名 假如你的数据库里已经有了一张数据表,且该表包含多个字段,你希望通过Django直接访问该数据表的各个字 ...