Java 单元测试中的 Mockito 使用详解与实战指南

文章目录

  • [1. 为什么要使用mock](#1. 为什么要使用mock)
  • [2. Mock 方法](#2. Mock 方法)
  • [3. 验证和断言](#3. 验证和断言)
  • [4. 给对象打桩](#4. 给对象打桩)
  • [5. @Mock 注解](#5. @Mock 注解)
  • [6. @BeforeEach 和 @AfterEach](#6. @BeforeEach 和 @AfterEach)
  • [7. Spy 方法 和 @Spy 注解](#7. Spy 方法 和 @Spy 注解)

1. 为什么要使用mock

  • Mock可以理解为创建一个虚假的对象,或者说模拟出一个对象,在测试环境中用来替换掉真实的对象,以达到:
  1. 验证该对象的某些方法的调用情况,调用了多少次,参数是多少
  2. 给这个对象的行为做一个定义,来指定返回结果或者指定特定的动作

2. Mock 方法

  • mock方法来自org.mockito.Mock,它表示可以mock一个对象或者是接口
java 复制代码
publie static <T> T mock(Clas<T> classToMock)

1、classToMock :待 mock 对象的 class 类

2、返回mock出来的类

  • 实例:使用 mock 方法 mock 一个类
java 复制代码
	Random random = Mockito.mock(Random.class);
	System.out.println(random.nextInt()); //这里表示调用了一次,等同于如下 只验证一次
	// 验证模拟的 random 对象 是否用到了 nextInt 方法,后面也可以接模拟对象调用的次数
	Mockito.verify(random, Mockito.times(1)).nextInt();  // 0
  • 如上不对其行为进行定义的话,则 mock 对象方法返回值为返回类型的默认值,所以上面的案例只返回 0(int 默认值为 0)

3. 验证和断言

  • 验证是校验待验证的对象是否发生过某些行为,Mockito 中验证的方法是: verify
java 复制代码
verify(mock).someMethod("some arg");
verify(mock, times(1)).someMothod("some arg");
  • 使用verify验证:
  • verify 配合 time() 方法,可以校验某些操作发生的次数
java 复制代码
@Test
void check() {
    Random random = Mockito.mock(Random.class, "test1");
    System.out.println(random.nextInt());
    System.out.println(random.nextInt());
    Mockito.verify(random, Mockito.times(2));
}
  • 断言使用的类是 Assertions
java 复制代码
Random random = Mockito.mock(Random.class, "test1");
Assertions.assertEquals(100, random.nextInt());
  • 当使用 Mock 对象时,如果不对其行为进行定义,则 mock 对象方法的返回值为返回类型的默认值

4. 给对象打桩

  • 打桩的意思是给 mock 对象规定一行的行为,使其按照我们的要求来执行具体的操作
  • nextInt() 打桩
java 复制代码
	Random random = Mockito.mock(Random.class, "test1");
	// 当 random 对象执行 nextInt 方法,永远返回 100
	Mockito.when(random.nextInt()).thenReturn(100);
	// 第一个参数表示 期待值,第二个参数表示 实际值
	Assertions.assertEquals(100, random.nextInt());
  • 把上面断言的期待值改为 101,就会报异常了

5. @Mock 注解

  • 可以理解为:快速创建 mock 的方法,可以使用 @mock 注解更为方便
  • 注意:Mock 注解需要搭配 MockitoAnnotations.initMocks(testClass) 方法一起使用

老版本搭配的方法:MockitoAnnotations.initMocks(testClass);

java 复制代码
@Mock
private Random random;
等价于
Random random = Mockito.mock(Random.class);
  • 上面的案例可以改为:
java 复制代码
@Mock
private Random random;

@Test
void check() {
    MockitoAnnotations.initMocks(this);
    Mockito.when(random.nextInt()).thenReturn(100);
    Assertions.assertEquals(100, random.nextInt());
}

6. @BeforeEach 和 @AfterEach

  • 在 Junit 5 的,@Before@After 注解被 @BeforeEach@AfterEach 所替代
java 复制代码
@BeforeEach
void before() {
    System.out.println("---测试前准备---");
}

@Test
void check() {
    MockitoAnnotations.initMocks(this);
    Mockito.when(random.nextInt()).thenReturn(100);
    Assertions.assertEquals(100, random.nextInt());
}

@AfterEach
void afeter() {
    System.out.println("---测试结束 ---");
}

7. Spy 方法 和 @Spy 注解

  • spy 方法 和 mock 方法的不同点:
  1. 被 spy 的对象会走真实的方法,而 mock 对象不会,mock 对象
  2. spy() 方法的参数是对象实例,mock 的参数是 class
  • 使用 spy 方法案例:
java 复制代码
@Spy
private Demo random;

@BeforeEach
void before() {
	// 执行初始化
    MockitoAnnotations.initMocks(this);
}

@Test
void check() {
// 没有打桩,random 执行的就是真实的方法
	Assertions.assertEquals(100, random.add(1,2));
}
java 复制代码
@Test
void check() {
	// 打桩后,执行的就是打桩的方法
	Mockito.when(random.add(1,2)).thenReturn(3);
	Assertions.assertEquals(100, random.add(1,2));
}
相关推荐
Boilermaker19926 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维6 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
MM_MS6 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
꧁Q༒ོγ꧂7 小时前
LaTeX 语法入门指南
开发语言·latex
njsgcs7 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
alonewolf_997 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子7 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34167 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
古城小栈7 小时前
Rust 迭代器产出的引用层数——分水岭
开发语言·rust
ghie90907 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab