测试类中Jackson ObjectMapper Mock注入失败问题求助
问题分析
你的ObjectMapper无法被Mockito注入的核心原因有两个:
- final字段+构造函数内硬编码实例化:
objectMapper是final修饰的成员变量,且在抽象类构造函数中直接通过new ObjectMapper()创建实例,一旦初始化完成,Mockito无法替换这个final字段的值。 - 手动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
相关产品推荐
相关产品推荐

