junit5
注解
注解 | 描述 |
---|---|
@Test | 表示方法是测试方法。与junit4的@Test注解不同的是,这个注解没有任何属性,因为junit jupiter中的测试扩展是基于它们自己的专用注解来操作的 |
@ParameterizedTest | 表示方法是参数化测试 |
@RepeatedTest | 表示方法是用于重复测试的测试模板 |
@TestFactory | 表示方法是用于动态测试的测试工厂 |
@TestTemplate | 表示方法是测试用例的模板 |
@TestInstance | 用于为被注解的测试类配置测试实例生命周期 |
@DisplayName | 声明测试类或测试方法的自定义显示名称 |
@BeforeEach | 表示被注解的方法应在每个测试方法之前执行,类似于junit4@Before |
@AfterEach | 表示被注解的方法应在每个测试方法之后执行,类似于junit4@After |
@BeforeAll | 表示被注解的方法应在所有测试方法之前执行,类似于junit4@BeforeClass |
@AfterEach | 表示被注解的方法应在所有测试方法之前执行,类似于junit4@AfterClass |
@Nested | 表示被注解的类是一个嵌套的非静态测试类 |
@Tag | 在类或方法级别声明标签,用于过滤测试 |
@Disabled | 用于禁用测试类或测试方法,类似junit4的@Ignore |
@ExtendWith | 用于注册自定义扩展 |
@Test、@TestTemplate、@RepeatedTest、@BeforeAll、@AfterAll、@BeforeEach、@AfterEach注解的方法不能有返回值
显示名称
@DisplayName("测试类")
public class DisplayNameTest {
@Test
@DisplayName("测试方法一")
void test01(){
}
@Test
@DisplayName("测试方法二")
void test02(){
}
}
- 测试类和测试方法可以声明自定义显示名称
- 可以使用空格、特殊字符、汉字、甚至emojis表情符号
禁用
禁用测试案例
@Disabled
public class DisabledTesst {
@Test
void test01(){
System.out.println("test01");
}
}
禁用测试方法
public class DisabledTesst {
@Test
@Disabled
void test01(){
System.out.println("test01");
}
@Test
void test02(){
System.out.println("test02");
}
}
不可同时在类和方法上加@Disabled注解,否则方法上的将不会生效
生命周期
- 为了允许隔离执行单个的测试方法,并避免由于可变测试实例状态而产生的意外副作用,junit在执行每个测试方法之前创建每个测试类的新实例
- “per-method”测试实例是junit中的默认行为
- 如果希望在同一个测试实例上测试所有方法需要
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
per-class可以在非静态方法上使用@BeforeAll和@AfterAll
嵌套测试
@DisplayName("外层测试实例")
public class TestingDemo {
@Test
@DisplayName("外层方法")
void test01(){
}
@DisplayName("内层测试实例")
@Nested
class WhenNew{
@Test
@DisplayName("内层方法")
void test(){
}
}
}
- 如果不加@Nested内层实例和内层方法将无法执行
- 添加@Nested后可以统一执行内外层,也可以单独执行内层方法
构造函数和方法依赖注入
在之前的所有junit版本中,测试构造函数或方法都不允许有参数
- parameterResolver定义了测试扩展的api,希望在运行时动态解析参数
- 如果测试方法接收参数,则该参数必须在运行时有已注册的parameterResolver解析
目前有桑自动注册的内置解析器:
TestInfoParameterResolver
:参数是TestInfo,可以用来获取当前测试有关的信息RepetitionInfoParameterResolver
:参数是RepetitionInfo,可以获取@RepeatedTest的重复数TestReporterParameterResolver
:参数是TestReporter
,可以发布当前测试运行的额外数据
其他参数解析器必须通过@Extendwith 注册适当的扩展来显示启用
接口测试和默认方法
- 允许在接口的default方法中声明测试注解
- 如果接口或测试类用
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
则可以在接口的default方法中声明@BeforeAll和@AfterAll
重复测试
@RepeatedTest(10)
void test01(){}
- 使方法重复执行指定次数
- 方法上不需要添加@Test
参数化测试
@ParameterizedTest
@ValueSource(strings = {"a","b"})
void test01(String s){
System.out.println(s);
}
- 使用@ParameterizedTest声明测试实方法
- @ValueSource:可以让你指明一个原生类型的数组,并且只能每次调用一个参数
@ParameterizedTest
@EnumSource(TimeUnit.class)
void test02(TimeUnit timeUnit){
System.out.println(timeUnit);
}
- @EnumSource:可以指定一个枚举,每次调用一个枚举实例
@ParameterizedTest
@MethodSource("stringStream")
void test03(String s){
System.out.println(s);
}
static Stream<String> stringStream(){
return Stream.of("aaa","bbb");
}
- @MethodSource:允许你传入一个返回stream、iterable、iterator或数组的静态工厂方法
@ParameterizedTest
@CsvSource({"aaa,111","bbb,222"})
void test04(String s, Integer i){
System.out.println(s+":"+i);
}
- @CsvSource:允许将参数列表以逗号分隔
@ParameterizedTest
@CsvFileSource(resources="/myTest.csv")
void test05(String s, Integer i){
System.out.println(s+":"+i);
}
- @CsvFileSource:可以使用classpath中的csv文件
@ParameterizedTest
@ArgumentsSource(MyArgumentsProvider.class)
void test06(String s){
System.out.println(s);
}
static class MyArgumentsProvider implements ArgumentsProvider{
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
return Stream.of("aaa","bbb").map(Arguments::of);
}
}
- @ArgumentsSource:指向一个自定义的,可重用的ArgumentsProvider实现类