You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试类中Jackson ObjectMapper Mock注入失败问题求助

问题分析

你的ObjectMapper无法被Mockito注入的核心原因有两个:

  1. final字段+构造函数内硬编码实例化:objectMapper是final修饰的成员变量,且在抽象类构造函数中直接通过new ObjectMapper()创建实例,一旦初始化完成,Mockito无法替换这个final字段的值。
  2. 手动mock覆盖@InjectMocks逻辑:你在@BeforeAll中手动调用Mockito.mock()创建AbstractClientRepository实例,这会覆盖@InjectMocks原本要创建的实例,导致Mockito的自动注入流程失效。
解决方案

方案一:重构抽象类,支持ObjectMapper依赖注入

修改抽象类的构造方式,让ObjectMapper通过构造函数注入,而非内部硬编码实例化:

protected final ObjectMapper objectMapper;
private final String apiName;
@Autowired private MeliRestClient restClient;

// 通过构造函数接收外部传入的ObjectMapper
public AbstractClientRepository(String apiName, ObjectMapper objectMapper) {
  this.apiName = apiName;
  this.objectMapper = objectMapper;
  // 保留JavaTimeModule注册逻辑
  this.objectMapper.registerModule(new JavaTimeModule());
}

如果项目基于Spring,也可以直接通过@Autowired注入ObjectMapper字段(需确保Spring容器中存在ObjectMapper的Bean):

@Autowired
protected final ObjectMapper objectMapper;
private final String apiName;
@Autowired private MeliRestClient restClient;

public AbstractClientRepository(String apiName) {
  this.apiName = apiName;
  this.objectMapper.registerModule(new JavaTimeModule());
}

这种方式下,测试时Mockito的@Mock和@InjectMocks就能正常注入你定义的ObjectMapper mock实例。

方案二:调整测试代码,手动注入ObjectMapper

如果不想修改抽象类代码,可以通过Mockito构造参数mock+反射注入的方式解决:

@Mock
private MeliRestClient restClient;

@Mock
private MeliRequestBuilder requestBuilderMock;

@Mock
private ObjectMapper objectMapper;

// 移除static修饰,避免和手动创建实例冲突
private AbstractClientRepository abstractClientRepository;

private static final String poolName = "pool";

@BeforeAll
public static void setUp() throws RestException {
  RoutingHelper.setMeliContext(MeliContextBuilder.build(Collections.emptyMap()));
}

@BeforeEach
public void init() {
  // 创建mock时指定构造参数,传入mock的ObjectMapper
  abstractClientRepository = Mockito.mock(
    AbstractClientRepository.class,
    Mockito.withSettings()
      .useConstructor(poolName, objectMapper)
      .defaultAnswer(Mockito.CALLS_REAL_METHODS)
  );
  // 手动注入restClient
  ReflectionTestUtils.setField(abstractClientRepository, "restClient", restClient);
}

这里通过useConstructor将mock的ObjectMapper传入抽象类构造函数,确保构造逻辑使用的是你定义的mock实例;再用ReflectionTestUtils手动注入restClient,绕开@InjectMocks的自动注入逻辑。

内容的提问来源于stack exchange,提问作者ZottoSL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 16:02:58