跳过正文
  1. 博客/
  2. 后端/
  3. 框架/

Mockito资料整理

·5 分钟· ·
后端 框架 Java 单元测试
目录

背景
#

网上Mockito 资料我看了一下很多都不够清晰,我总结一下我在使用 Mockito 常用的方法

Mockito 局限
#

  • 无法模拟 final 方法(需 Mockito 4.10+ 支持 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker 添加 mock-maker-inline
  • 静态方法不支持(需 Mockito 3.x+ 支持MockedStatic<Utils> mockedStatic = mockStatic(Utils.class)
  • 私有方法,不支持(需要PowerMockito)也不推荐测试私有方法

Mockito 处理依赖注入
#

  • 通过 @InjectMocks 注入到被测类(被测试类可以添加 Spy 注解 不可添加Mock注解)
  • 只会注入一层,嵌套的不会注册(且假如Mock对象上面有 InjectMocks 注解也不会将其注入) 代码必须不违背迪米特原则,就可以使用mock自动依赖注入

Mock 与 Spy 的区别总结
#

特性 Mock 对象 Spy 对象
默认行为 所有方法默认被模拟,不执行真实逻辑 默认调用真实方法,需显式打桩才会模拟
创建方式 mock(Class)@Mock spy(真实对象)@Spy
适用场景 完全隔离依赖,避免外部交互(如数据库、API) 部分保留真实逻辑,仅模拟特定方法(如耗时操作)
对未打桩方法的处理 返回默认值(如 null0 执行真实方法
性能开销 轻量级,无真实对象实例化 需要创建真实对象,可能有初始化成本,构造器假如没有无参构造器会传入null
在SpringBoot中使用 @MockBean @SpyBean

Argument Matcher 常用总结
#

场景 推荐匹配器 示例
精确值验证 eq() eq("expected")
类型无关匹配 any() / any(Class<T>) any(User.class)
基础类型通配 anyInt(), anyString() when(...).thenReturn(...)
复杂对象属性验证 自定义 ArgumentMatcher argThat(user -> ...)
空值处理 isNull() / nullable() nullable(String.class)

Argument Matcher 用法对比表​
#

​场景​ ​核心用法​ ​示例​ ​注意事项​ ​引用来源​
verify() 验证方法调用时的参数匹配规则,需全参数使用匹配器。 verify(mock).someMethod(anyInt(), eq("test")) 若方法有多个参数,只要一个参数使用匹配器,其他参数也需匹配器(如 eq())否则抛异常。 1

5

8
when().thenReturn() 对非 void 方法进行桩方法配置,参数匹配后返回指定值。 when(mock.get(anyInt())).thenReturn("element") 若方法为 void,需改用 doReturn();若使用 Spy 对象,真实方法会被执行,可能触发异常。 1

5

7
doReturn().when() 对任意方法(包括 void)进行桩方法配置,直接覆盖行为,不执行真实逻辑。 doReturn("mockValue").when(mock).method(argThat(s -> s.length() > 5)) 适用于需要跳过真实方法执行的场景(如 Spy 对象、void 方法或异常方法)。 7

8

11

verify 方法用法对比表​
#

​参数形式​ ​作用​ ​常用模式(VerificationMode)​ ​示例​ ​注意事项​
verify(mock) 验证方法 ​​是否被调用一次​​(默认次数为1)。 无(隐式调用 times(1) java<br>verify(mockList).add("test");<br> 等同于 verify(mock, times(1))。若方法未被调用或次数不符,测试失败。
verify(mock, mode) 验证方法 ​​调用次数或特定行为​​,支持灵活的条件约束。 times(n):精确调用次数
atLeast(n):至少调用次数
atMost(n):最多调用次数
never():从未调用
atLeastOnce():至少一次 -timeout(1000) : 异步超时
java<br>// 验证 add("test") 调用2次<br>verify(mockList, times(2)).add("test");<br><br>// 验证从未调用 clear()<br>verify(mockList, never()).clear(); 1. 若混合使用参数匹配器(如 any()),需确保所有参数均使用匹配器(如 eq())。
2. 可组合使用 timeout() 验证异步调用超时。

​JUnit Jupiter API 常用 Assertions 方法总结表​​:

​断言方法​ ​功能描述​ ​示例​ ​注意事项​ ​引用来源​
assertEquals 验证期望值(expected)与实际值(actual)是否相等。 assertEquals(2, Math.addExact(1, 1)) 对象比较使用 equals() 方法;支持通过 Supplier 延迟生成错误消息(失败时触发)

1

6

1

6

8
assertTrue/assertFalse 验证条件是否为真(或假)。 assertTrue(1 < 2, "条件应为真")
assertFalse(1 > 2)
支持布尔表达式或 BooleanSupplier,失败时显示自定义消息

6

8

10

6

8

10
assertNull/assertNotNull 验证对象是否为 null(或不为 null)。 assertNull(optional.orElse(null))
assertNotNull(new Object())
常用于验证方法返回值的空性

6

8

10

6

8

10
assertSame/assertNotSame 验证两个对象引用是否指向同一对象(或不同对象)。 assertSame(obj1, obj1)
assertNotSame(new Object(), new Object())
使用 - 比较引用地址

6

8

10

6

8

10
assertArrayEquals 验证两个数组的内容是否相等(包括长度和元素顺序)。 assertArrayEquals(new int[]{1,2}, new int[]{1,2}) 支持基本类型数组和对象数组;元素类型需一致

1

8

10

1

8

10
assertThrows 验证执行代码块是否抛出指定类型的异常。 assertThrows(ArithmeticException.class, () -> Math.floorDiv(1, 0)) 返回异常实例,可进一步验证异常信息(如 getMessage()

1

6

8

1

6

8
assertTimeout 验证代码块是否在指定时间内完成执行。 assertTimeout(Duration.ofSeconds(1), () -> Thread.sleep(500)) 超时后立即抛出失败;支持 Duration 时间单位

1

8

9

1

8

9
assertAll 批量验证多个断言,全部通过才算成功。 assertAll("批量验证", () -> assertEquals(1,1), () -> assertTrue(2 > 1)) 所有断言均会执行,失败时汇总所有错误信息

1

8

10

1

8

10
fail 强制测试失败,用于标记未实现的测试或逻辑分支。 fail("测试未完成") 常用于异常分支或条件不满足时的快速终止

6

8

10

6

8

10

​补充
#

Java8 Maven 依赖:

<dependency>    
    <groupId>org.mockito</groupId>    
    <artifactId>mockito-core</artifactId>    
    <version>4.11.0</version> <!-- Java 8 兼容版本 -->    
    <scope>test</scope>    
</dependency>    
<dependency>    
    <groupId>org.mockito</groupId>    
    <artifactId>mockito-junit-jupiter</artifactId>    
    <version>4.11.0</version> <!--  mockito-core 版本一致 -->    
    <scope>test</scope>    
</dependency>  
  

相关文章

设计模式探索:从原则到实践
·15 分钟
框架 后端 Java
背景 # 在公司推进DDD中,我发现即使代码按照DDD进行分层,但是底层代码还是阅读性比较差,只不过被分到不同的子服务中。怎么让代码更加整洁规范呢?我觉得可以采用设计模式,所以我花了点时间重新学习了所有的设计模式。
大话DDD
·11 分钟
后端 框架 Java
背景 # 什么是DDD,DDD全名 Domain Driven Design,是一种架构设计方法,和我们普通的设计模式有什么区别呢,我们知道设计模式有单例、工厂这些,这些东西只和代码有关,他是一种手法,可以看作是一个小手段,就是类似孔己己的茴香豆7种写法一样
大话Java精度问题
·7 分钟
后端 框架 Java
背景 # 事情的起因是,正当我悠闲的品尝一杯Java Caffe的时候,突然飞书一个加急信息铺面而来,“小张啊,你快看下,线上有个用户用优惠券少付一分钱“
优化Spring单元测试:从90秒到18秒的实战经验
·5 分钟
后端 框架 Java
引言 # 在大型Spring Boot项目中,缓慢的单元测试执行速度常常成为开发效率的瓶颈。以我司项目为例,原本的单元测试套件需要约90秒才能完成,严重影响了开发流程。经过系统性的优化,我们成功将测试时间缩短至18秒,提升了80%的效率。本文将详细介绍这些优化手段及其原理。
深入理解Java中的synchronized机制
·5 分钟
后端 框架 Java JVM
一、synchronized概述 # synchronized是Java语言中用于控制并发访问的关键字,它是一种排他锁(独占锁)和可重入锁。作为Java内置的同步机制,它能够确保在同一时刻只有一个线程可以访问被保护的代码块或方法。
秒杀系统的思考
·2 分钟
后端 框架 Java
秒杀系统