JUnit和Mockito
简介
JUnit 是一个 Java 编程语言色单元测试框架。单元测试(Unit testing),是指对软件中最小可测试单元进行检查和验证,Java 单元测试指一个类。总的来说,单元就是认为规定的最小的被测功能模块。
- Junit4:单元测试框架
- Mockito:生成模拟对象
依赖
<!-- JUnit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
JUnit4
- 测试方法:用
@Test注解的一些函数 - 测试类:包含一个或多个测试方法的一个
*Test.java文件 - 测试集:是一个suite,可能包含多个测试类
- 测试运行器:决定了用什么方式偏好去运行这些测试集/类/方法
@RunWith
修饰类,用于修改运行器,如果不指定 @RunWith 则使用默认运行器。当测试类被 @RunWith 注解修饰时,或者类继承了一个被该注解修饰的类,JUnit 将会使用这个注解所指明的运行器来运行单元测试,而不使用JUnit默认的运行器。
@RunWith(JUnit4.class) // junit4的默认运行器
@RunWith(SpringRunner.class) // 集成了spring的一些功能的运行器
@Test
在 Junit3 中,是通过对测试类和测试方法的命名来确定是否测试,且所有的测试类必须继承 Junit 的测试基类。在 Junit4 中,只需要在方法前加上 @Test 即可。
将一个普通方法修饰为一个测试方法,可选参数:timeout、excepted:
@Test(timeout = 1000) // 设置被修饰的测试方法在预期时间内执行完成,否则测试失败
@Test(expected = Exception.class) // 设置被修饰的测试方法应该抛出的预期异常,异常类型为:Exception.class
// 如果测试方法没有抛出预期异常,则测试失败; 例:@Test(expected = NullPointException.class)
注:测试方法必须是public void,即公共、无返回
@BeforeClass
用于修饰测试类中的非测试方法,该方法将在其所属测试类中的所有方法执行前运行,且只运行一次,可用于做一些测试基础准备,比如数据库连接、读取文件等。
注:@BeforeClass修饰的方法必须是被public static void修饰的方法,即公开、静态、无返回
@AfterClass
同BeforeClass相反,注解用于修饰测试类中的非测试方法,该方法将在其所属测试类中所有测试方法执行完成后运行,且只运行一次;可用于做一些测试后续操作,比如断开数据库连接,关闭文件等。
注:@AfterClass修饰的方法必须是被public static void修饰的方法,即公开、静态、无返回
@Before
修饰测试类中的非测试方法,该方法会在其所属测试类中的每个测试方法运行前执行一次;主要用于为单个测试方法做一些基础的测试准备工作。
注:@Before修饰的方法必须是被public void修饰的方法,即公开、无返回,但不能被static修饰
@After
修饰测试类中的非测试方法,同@Before相反,该方法会在其所属测试类中的每个测试方法执行完成后运行一次。
注:@After修饰的方法必须是被public void修饰的方法,即公开、无返回,但不能被static修饰
@Ignore
注释掉一个测试方法或一个类,被注释的方法或类,不会被执行;但不建议经常这么做,容易忘记更新这些测试代码,导致代码不够干净,用例遗漏
断言
| 断言 | 备注 |
|---|---|
assertEquals(boolean expected, boolean actual) | 查看两个对象是否相等。类似于字符串比较使用的equals()方法 |
assertTrue(boolean expected, boolean actual) | 检查条件为真 |
assertNull(Object object) | 检查对象为空 |
assertSame(boolean condition) | 查看两个对象的引用是否相等。类似于使用“==”比较两个对象 |
assertArrayEquals(expectedArray, resultArray) | 检查两个数组是否相等 |
assertThat(actual, matcher) | 查看实际值是否满足指定的条件 |
fail() | 让测试失败,通常被用于标记某个不应该被到达的分支,如在一个预期发生的异常之后) |
Mockito
Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。Mock 可以分解在单元测试中耦合的其他类或者接口,它能帮助模拟这些依赖,并验证所调用的依赖的行为。
使用范畴:
- 真实对象很难被创建
- 真实对象的某些行为很难被触发
- 真实对象实际上不存在
Mockito基本概念
- 桩函数(stub):实际上是白盒测试中的概念,意思是适用一些自定义的测试函数来替换当前需要测试的函数,被替换的函数可能是目前没有写完的函数,这样能够加速开发,或更好的找错误源;
- 打桩(存根):模拟要调用的函数(打桩对象),给它提供桩函数,给桩函数一个返回值。简单说就是自定义输入输出,不打桩默认返回null。如果用函数 a1 代替 a,那么 a 称为原函数,a1 称为桩函数,打桩就是编写或生成桩代码。
@RunWith
必须使用
@RunWith(MockitoJUnitRunner.class)或MockitoAnnotations.initMocks进行mocks的初始化和注入
@RunWith(MockitoJUnitRunner.class) // MockitoJUnitRunner类用于检查是否创建了所有模拟并在需要时自动装配
@Mock
用于模拟对象,有助于最大程度减少重复模拟现象,代替在不使用注解的场景中使用的Mockito.mock(xxx.class)方法
@Spy
用spy监控真实对象,设置真实对象行为
@InjectMocks
Mockito通过此注解会自动注入 mocks 对象到注解的变量中。如果注入失败,不会通知我们,所以需要自己对失败的对象做处理。
常用方法
| 示例 | 备注 |
|---|---|
when(mock.someMethod()).thenReturn(value) | Mock 对象某个方法调用时的返回值 |
when(mock.someMethod()).thenThrow(new RuntimeException) | 当调用某个方法时抛出的异常 |
doThrow(new RuntimeException()).when(mockedList).clear() | 当执行mockedList.clear()时,会抛出RuntimeException |
verify(mock, times(5)).someMethod() | 验证 Mock 对象函数是否执行、执行次数,可以为times(x), atLeastOnce() 或者 never() |
常见问题
Mockito初始化
- 在单元测试中使用 @Mock, @Spy, @InjectMocks 等注解时,需要进行初始化后才能使用
- MockitoAnnotations.initMocks(this):其中this就是单元测试所在的类,在initMocks函数中Mockito会根据类中不同的注解(如@Mock, @Spy等)创建不同的mock对象,即初始化工作
@Mock和@InjectMocks
- @Mock: 创建一个 Mock
- @InjectMocks: 创建一个实例,这个 Mock 可以调用真实代码的方法,其余用 @Mock(或 @Spy)注解创建的 mock将被注入到用该实例中
@Mock和@Spy
- @spy 的参数是对象示例,mock 的参数是 class
- 被 spy 的对象,调用其方法时默认会走真实方法,mock 对象不会
本文介绍了如何使用JUnit4进行单元测试,包括@RunWith、@Test、@BeforeClass、@AfterClass等注解的使用。同时,详细阐述了Mockito的基本概念和常用方法,如@Mock、@Spy、@InjectMocks,以及如何解决Mockito初始化和注解配合使用时的常见问题。

2257

被折叠的 条评论
为什么被折叠?



