JUnit和Mockito

本文介绍了如何使用JUnit4进行单元测试,包括@RunWith、@Test、@BeforeClass、@AfterClass等注解的使用。同时,详细阐述了Mockito的基本概念和常用方法,如@Mock、@Spy、@InjectMocks,以及如何解决Mockito初始化和注解配合使用时的常见问题。

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 对象不会
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值