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

Mockito能否模拟深层内部函数返回值?ServiceImpl测试场景问询

测试ServiceImpl时模拟SomeSM中parsedJson值的方案

针对你的需求,分两种场景给出具体实现方案:

场景一:仅测试ServiceImpl的业务逻辑(无需验证SomeSMImpl内部转换)

这种情况最直接,因为ServiceImpl依赖的是SomeSM接口,我们可以直接用Mockito mock这个接口,让它的两个方法返回预设好的rawResult(对应你期望的parsedJson转换后的结果),完全跳过SomeSMImpl的内部逻辑,专注测试ServiceImpl中从rawResult到finalResult的处理逻辑。

测试代码示例(JUnit 5 + Mockito)

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.Map;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class ServiceImplTest {

    @Mock
    private SomeSM someSM; // 对接口进行mock

    @InjectMocks
    private ServiceImpl serviceImpl; // 将mock的someSM注入到待测试的ServiceImpl中

    @Test
    public void testProcess() throws Exception {
        // 1. 构造测试用的请求参数
        Map<String, Object> requestBody = new HashMap<>();
        // 根据实际业务填充requestBody内容

        // 2. 预设两个第三方接口处理后的rawResult(对应你想要的parsedJson转换结果)
        Map<String, Object> mockRawResult01 = new HashMap<>();
        mockRawResult01.put("key1", "value_from_parsedJson_01");
        Map<String, Object> mockRawResult02 = new HashMap<>();
        mockRawResult02.put("key2", "value_from_parsedJson_02");

        // 3. 指定mock对象的方法返回值
        when(someSM.callThirdPartyProcess01(org.mockito.ArgumentMatchers.anyMap())).thenReturn(mockRawResult01);
        when(someSM.callThirdPartyProcess02(org.mockito.ArgumentMatchers.anyMap())).thenReturn(mockRawResult02);

        // 4. 调用待测试方法
        Map<String, Object> finalResult = serviceImpl.process(requestBody);

        // 5. 验证最终结果是否符合预期
        assertEquals("expected_final_value", finalResult.get("expected_final_key"));
    }
}

场景二:同时验证SomeSMImpl的parsedJson转换逻辑 + ServiceImpl的业务逻辑

如果需要确保SomeSMImpl中从parsedJson到rawResult的映射逻辑正确,再测试ServiceImpl的处理,就需要先mockHttpRequestHelper的postHTTPS方法,让它返回我们预设的parsedJson,再用真实的SomeSMImpl实例注入到ServiceImpl中测试。

第一步:调整SomeSMImpl代码(支持依赖注入)

原代码中HttpRequestHelper是直接new出来的,无法mock,需要改成构造注入:

@Service
public class SomeSMImpl implements SomeSM {

    private final HttpRequestHelper httpHelper;

    // 构造注入HttpRequestHelper,方便测试替换为mock对象
    @Autowired
    public SomeSMImpl(HttpRequestHelper httpHelper) {
        this.httpHelper = httpHelper;
    }

    @Override
    public Map callThirdPartyProcess01(Map payload) throws Exception {
        Map rawResult = new HashMap();
        Map parsedJson = httpHelper.postHTTPS(payload.get("headers"), payload.get("body"), payload.get("params"), Map.class);

        if(parsedJson.get("api_code") != null)
            // 你的parsedJson到rawResult的映射逻辑
            rawResult.put("processed_key", parsedJson.get("api_code"));

        return rawResult;
    }

    @Override
    public Map callThirdPartyProcess02(Map payload) throws Exception {
        Map rawResult = new HashMap();
        Map parsedJson = httpHelper.postHTTPS(payload.get("headers"), payload.get("body"), payload.get("params"), Map.class);

        if(parsedJson.get("api_code") != null)
            // 你的parsedJson到rawResult的映射逻辑
            rawResult.put("another_processed_key", parsedJson.get("api_code"));

        return rawResult;
    }
}

第二步:编写测试代码

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.Map;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class ServiceImplWithRealSomeSMTest {

    @Mock
    private HttpRequestHelper httpHelper; // mock第三方请求工具类

    @InjectMocks
    private SomeSMImpl someSMImpl; // 将mock的httpHelper注入真实的SomeSMImpl

    private ServiceImpl serviceImpl;

    // 初始化ServiceImpl,注入真实的SomeSMImpl实例
    public ServiceImplWithRealSomeSMTest() {
        serviceImpl = new ServiceImpl();
        serviceImpl.setSomeSM(someSMImpl);
    }

    @Test
    public void testProcessWithMockedParsedJson() throws Exception {
        // 1. 构造测试用的请求参数
        Map<String, Object> requestBody = new HashMap<>();
        // 根据实际业务填充requestBody,确保能生成正确的params01和params02

        // 2. 预设第三方API返回的parsedJson
        Map<String, Object> mockParsedJson01 = new HashMap<>();
        mockParsedJson01.put("api_code", "200");
        mockParsedJson01.put("data", "test_data_01");

        Map<String, Object> mockParsedJson02 = new HashMap<>();
        mockParsedJson02.put("api_code", "200");
        mockParsedJson02.put("data", "test_data_02");

        // 3. 指定mock的httpHelper返回预设的parsedJson
        // 两次调用分别返回不同的parsedJson
        when(httpHelper.postHTTPS(org.mockito.ArgumentMatchers.any(), 
                                  org.mockito.ArgumentMatchers.any(), 
                                  org.mockito.ArgumentMatchers.any(), 
                                  org.mockito.ArgumentMatchers.eq(Map.class)))
                .thenReturn(mockParsedJson01)
                .thenReturn(mockParsedJson02);

        // 4. 调用待测试方法
        Map<String, Object> finalResult = serviceImpl.process(requestBody);

        // 5. 验证逻辑:先验证SomeSMImpl的转换是否正确,再验证ServiceImpl的最终结果
        Map<String, Object> testRawResult01 = someSMImpl.callThirdPartyProcess01(new HashMap<>());
        assertEquals("200", testRawResult01.get("processed_key"));

        Map<String, Object> testRawResult02 = someSMImpl.callThirdPartyProcess02(new HashMap<>());
        assertEquals("200", testRawResult02.get("another_processed_key"));

        // 验证ServiceImpl生成的最终结果
        assertEquals("expected_final_value", finalResult.get("expected_final_key"));
    }
}

内容的提问来源于stack exchange,提问作者Dhana D.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:04:59