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.
相关产品推荐
相关产品推荐

