参考来源:
https://www.softwaretestinghelp.com/junit-annotations-tutorial/#Recommended_Reading
https://www.softwaretestinghelp.com/junit-tutorial/
https://doczhcn.gitbook.io/junit5/index/index-2/annotations
https://www.baeldung.com/junit-5-test-annotation
单元测试(Unit Testing)与Junit
单元测试是对小逻辑或代码的测试,只针对一小部分代码,可能只是一个方法或一个类
单元测试可以通过手动测试(Manual testing)和自动测试(Automated testing)完成
开发人员使用单元测试框架(Unit Test framework)来创建自动化的单元测试用例。
JUnit 是一个开源框架,用于在 Java 编程语言中编写和执行单元测试。它是最著名的单元测试框架之一
JUnit 注释 – JUnit 4 与 JUnit 5
test的执行会经历生命周期(lifecycle)的不同阶段:
1、在任何测试开始之前,需要执行一些活动
2、在各个测试进行之前,需要执行一些活动
3、在各个测试完成之后,需要执行一些活动
4、在所有测试结束之后,需要执行一些活动
这些活动由用户定义的函数完成,被称为生命周期回调方法(lifecycle call-back methods)
这些生命周期回调方法的行为由JUnit 中使用的内置“生命周期回调注释”确定。
JUNIT 4 ANNOTATION | JUNIT 5 ANNOTATION |
---|---|
@Before | @BeforeEach |
@After | @AfterEach |
@BeforeClass | @BeforeAll |
@AfterClass | @AfterAll |
@Test | @Test |
JUnit 5 的生命周期注释的顺序工作流如下:
Annotation的解释与使用规则:
使用@Test,@TestTemplate,@RepeatedTest,@BeforeAll,@AfterAll,@BeforeEach或@AfterEach注解的方法不能有返回值
测试类和测试方法都不必是public
@Before (JUnit 4) /@BeforeEach (JUnit 5):
- 带注释的方法在测试类中的每个测试方法执行之前执行。
- 当您希望在每个测试开始之前设置资源或测试数据时,可以使用此注释。
@After (JUnit 4) /@AfterEach (JUnit 5):
- 带注释的方法在测试类中的每个测试方法执行后执行。
- 当您希望在每个测试用例运行后必须释放使用的资源或测试数据时,可以使用此注释。
@BeforeClass (JUnit 4) /@BeforeAll (JUnit 5):
- 带注释的方法在执行测试类中的所有测试方法之前执行。
- 当您希望在类级别设置资源或测试数据时,可以使用此注释。
- 由于此方法使用 @BeforeClass 注释/@BeforeAll 仅对测试类执行一次,并且该方法的副本在整个类中共享,并且该方法必须声明为静态的。
@AfterClass (JUnit 4) /@AfterAll (JUnit 5):
- 带注释的方法在测试类中的所有测试方法执行后执行。
- 当您希望在类级别释放使用的资源或测试数据时,可以使用此注解。
- 由于此方法使用 @AfterClass 注释/@AfterAll 仅对测试类执行一次,并且该方法的副本在整个类中共享,因此该方法必须声明为静态的。
@Test(JUnit 4 和 JUnit 5):
- @Test 注解在 JUnit 4 和 JUnit 5 中很常见。注解的方法代表类中的测试用例。
- 在 JUnit 类中可能有多个方法,每个方法都用 @Test 注释。这意味着一个类可能有多个测试用例。
- Test 有不同的属性或参数可以传递。您可以为测试用例添加强制超时或添加异常。这将在单独的教程中详细介绍。
- 带注释的方法不能是私有的或静态的
- @Test 方法必须在 JUnit 4 中声明为 public,而 Junit 5 允许定义没有访问修饰符“public”的测试用例,因为默认情况下它认为“无访问修饰符”为“public”。
笔者注:对上一句的表述略有疑问,在IDEA中 选择了add Junit5.4 to classpath,经测试发现方法的访问修饰符public、protected、以及无访问修饰符(难道不是代表包访问权限,并非上文所说的“默认为public”吗?),都可成功
测试结果如下(注意左侧查找test的结果):
示例程序:
public class JUnit5Program {
@BeforeAll
public static void preClass() {
System.out.println("@BeforeAll – the annotated method runs once before all other methods execute");
}
@BeforeEach
public void setUp() {
System.out.println("_______________________________________________________\n");
System.out.println("@BeforeEach – the annotated method executes before each test ");
}
@Test
public void test_JUnit1() {
System.out.println("@Test – this is test case 1");
}
@Test
public void test_JUnit2() {
System.out.println("@Test – this is test case 2");
}
@Test
public void test_JUnit3() {
System.out.println("@Test – this is test case 3");
}
@AfterEach
public void tearDown() {
System.out.println("@AfterEach – the annotated method executes after each test executes");
System.out.println("_______________________________________________________\n");
}
@AfterAll
public static void postClass() {
System.out.println("@AfterAll – the annotated method runs once after all other methods execute");
}
}
运行结果:
一些细节
JUnit 首先构造一个新的类实例,然后调用带注释的方法
测试抛出的任何异常都会被 JUnit 报告为失败。如果没有抛出异常,则粗暴假定为测试成功
Junit4的Test
注解支持两个可选参数
1、expected,声明一个测试方法应该抛出一个异常。如果它没有抛出异常,或者它抛出的异常与声明的异常不同,则测试失败
@Test(expected=IndexOutOfBoundsException.class) public void outOfBounds() {
new ArrayList<Object>().get(1);
}
2、timeout:
如果测试花费的时间超过指定的时钟时间(以毫秒为单位),则会导致测试失败。以下测试失败
@Test(timeout=100) public void infinity() {
while(true);
}
注意,Junit5中的@test不能声明任何属性,因为JUnit Jupiter中的测试扩展需要通过专用的注解。