1. 概述
在对使用 Jackson 进行 JSON 反序列化的代码做单元测试时,一个高效的策略是 mock ObjectMapper#readValue()
方法。✅
这样做最大的好处是:无需在测试中构造冗长的 JSON 字符串输入,直接控制方法返回值,让测试更专注逻辑本身,而不是被数据格式绊住。
本文将演示如何使用 Mockito 实现这一目标,简洁高效,适合日常开发中“踩坑”后快速验证修复。
2. Maven 依赖
测试需要用到 Mockito 和 Jackson 的核心模块,以下是关键依赖:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
<type>bundle</type>
</dependency>
⚠️ 注意:jackson-databind
是 Jackson 反序列化的基础,务必引入。版本无需严格一致,但建议保持项目统一。
3. ObjectMapper 使用示例
先看一个简单的 Flower
类:
public class Flower {
private String name;
private Integer petals;
public Flower(String name, Integer petals) {
this.name = name;
this.petals = petals;
}
// 默认构造函数、getter 和 setter 省略
public String getName() {
return name;
}
public Integer getPetals() {
return petals;
}
public void setName(String name) {
this.name = name;
}
public void setPetals(Integer petals) {
this.petals = petals;
}
}
接下来是一个校验 JSON 字符串是否表示“有花瓣的花”的类:
public class FlowerJsonStringValidator {
private ObjectMapper objectMapper;
public FlowerJsonStringValidator(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public boolean flowerHasPetals(String jsonFlowerAsString) throws JsonProcessingException {
Flower flower = objectMapper.readValue(jsonFlowerAsString, Flower.class);
return flower.getPetals() > 0;
}
}
✅ 关键设计:ObjectMapper
通过构造函数注入 —— 这为后续 mock 提供了前提条件,属于典型的可测试性设计。
4. 使用 Mockito 进行单元测试
我们使用 JUnit 5 + Mockito 扩展来简化 mock 管理:
@ExtendWith(MockitoExtension.class)
public class FlowerJsonStringValidatorUnitTest {
@Mock
private ObjectMapper objectMapper;
private FlowerJsonStringValidator flowerJsonStringValidator;
@BeforeEach
public void setUp() {
flowerJsonStringValidator = new FlowerJsonStringValidator(objectMapper);
}
// 测试用例
}
✅ 编写测试:验证有花瓣的花返回 true
@Test
public void whenCallingHasPetalsWithPetals_thenReturnsTrue() throws JsonProcessingException {
Flower rose = new Flower("testFlower", 100);
when(objectMapper.readValue(anyString(), eq(Flower.class))).thenReturn(rose);
assertTrue(flowerJsonStringValidator.flowerHasPetals("this can be a very long json flower"));
verify(objectMapper, times(1)).readValue(anyString(), eq(Flower.class));
}
关键点解析:
when(...).thenReturn(...)
:直接指定readValue
返回一个预设的Flower
实例anyString()
:表示任意 JSON 字符串输入,无需真实构造eq(Flower.class)
:确保类型参数匹配,避免泛型擦除问题verify(...)
:验证readValue
确实被调用一次,确保逻辑路径正确
⚠️ 踩坑提示:如果不加 eq(Flower.class)
,可能会因参数匹配失败导致 mock 不生效,这是 Mockito 常见陷阱。
5. 总结
通过 mock ObjectMapper#readValue()
,我们可以:
- ✅ 脱离真实 JSON 字符串,简化测试数据准备
- ✅ 聚焦业务逻辑(如花瓣数量判断),而非 Jackson 解析细节
- ✅ 提升测试可读性和维护性,尤其适合复杂嵌套结构的场景
最终代码示例已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/testing-modules/mockito
📌 实践建议:只要 ObjectMapper
是注入的,就大胆 mock;如果是内部 new 出来的,先重构为依赖注入再测试。