使用 JUnit 编写单元测试
使用 JUnit 编写单元测试
一、构建单元测试
需要遵循一些命名习惯:如果有一个名为 createAccount 的被测试函数, 那么测试函数的名称应该是 test createAccount。
测试代码必须要做以下这几件事情:
- 准备测试所需要的各种条件(创建所有必须的对象, 分配必要的资源等等);
- 调用要测试的方法;
- 验证被测试方法的行为和期望是否一致;
- 完成后清理各种资源。
二、JUnit 的断言
JUnit 提供了一些辅助函数, 用于帮助确定某个被测试函数是否正常工作。通常将所有这些函数统称为断言;它可以确定:某条件是否为真;两个数据是否相等,或者不等,或者其他一些情况;
当一个失败或者错误出现的时候, 当前测试方法的执行流程将会被中止,但是(位于同一个测试类中的)其他测试将会继续运行;
断言是单元测试最基本的组成部分。因此,JUnit 程序库提供不同形式的多种断言:
【其中方法应用的时候由于其都是 static 方法,所以直接调用即可(如:Assert.assertEquals(1,1) )】
断言 | 含义 |
---|---|
assertArrayEquals(expecteds, actuals) | 查看两个数组是否相等。 |
assertEquals(expected, actual) | 查看两个对象是否相等。类似于字符串比较使用的equals()方法 |
assertNotEquals(first, second) | 查看两个对象是否不相等 |
assertNull(object) | 查看对象是否为空 |
assertNotNull(object) | 查看对象是否不为空 |
assertSame(expected, actual) | 查看两个对象的引用是否相等。类似于使用“==”比较两个对象 |
assertNotSame(unexpected, actual) | 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象 |
assertTrue(condition) | 查看运行结果是否为true |
assertFalse(condition) | 查看运行结果是否为false |
assertThat(actual, matcher) | 查看实际值是否满足指定的条件 |
fail(String message) | 让测试失败,常用于标记某个不应该执行的分支 |
Junit 5 断言官网: 跳转
三、JUnit 的注解
-
@Test
在junit3中,是通过对测试类和测试方法的命名来确定是否是测试,且所有的测试类必须继承junit的测试基类。在junit4中,定义一个测试方法变得简单很多,只需要在方法前加上@Test就行了。【注意:测试方法必须是public void,即公共、无返回数据。可以抛出异常】
-
@Ignore:
有时候我们想暂时不运行某些测试方法\测试类,可以在方法前加上这个注解。在运行结果中,junit会统计忽略的用例数来提醒你。但是不建议经常这么做,因为这样的坏处时,容易忘记去更新这些测试方法,导致代码不够干净,用例遗漏。使用此标注的时候不能与其它标注一起使用,如:和@Test 标注一起使用,那就没用了。 -
@BeforeClass:
当我们运行几个有关联的用例时,可能会在数据准备或其它前期准备中执行一些相同的命令,这个时候为了让代码更清晰,更少冗余,可以将公用的部分提取出来,放在一个方法里,并为这个方法注解@BeforeClass。意思是在测试类里所有用例运行之前,运行一次这个方法。例如创建数据库连接、读取文件等。
【注意:方法名可以任意,但必须是public static void,即公开、静态、无返回。这个方法只会运行一次】 -
@AfterClass:
跟@BeforeClass对应,在测试类里所有用例运行之后,运行一次。用于处理一些测试后续工作,例如清理数据,恢复现场。
【注意:同样必须是public static void,即公开、静态、无返回。这个方法只会运行一次】 -
@Before:
与@BeforeClass的区别在于,@Before不止运行一次,它会在每个用例运行之前都运行一次。主要用于一些独立于用例之间的准备工作。比如两个用例都需要读取数据库里的用户A信息,但第一个用例会删除这个用户A,而第二个用例需要修改用户A。那么可以用@BeforeClass创建数据库连接。用@Before来插入一条用户A信息。
【注意:必须是public void,不能为static。不止运行一次,根据用例数而定。】 -
@After:与@Before对应。
-
@Runwith:
首先要分清几个概念:测试方法、测试类、测试集、测试运行器。 -
测试方法就是用@Test注解的一些函数。
测试类是包含一个或多个测试方法的一个Test.java文件;
测试集是一个suite,可能包含多个测试类;
测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法;
而@Runwith就是放在测试类名之前,用来确定这个类怎么运行的。也可以不标注,会使用默认运行器。
示例代码:JunitFlowTest
public class JunitFlowTest {
/*
* 1.@BeforeClass修饰的方法会在所有方法被调用前被执行,
* 而且该方法是静态的,所以当测试类被加载后接着就会运行它,
* 而且在内存中它只会存在一份实例,它比较适合加载配置文件。
* 2.@AfterClass所修饰的方法通常用来对资源的清理,如关闭数据库的连接
* 3.@Before和@After会在每个测试方法的前后各执行一次。
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("this is beforeClass...");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("this is afterClass...");
}
@Before
public void setUp() throws Exception {
System.out.println("this is before...");
}
@After
public void tearDown() throws Exception {
System.out.println("this is after");
}
@Test
public void test1() {
System.out.