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

如何为RestTemplate场景下含异常分支的if-else逻辑编写Junit测试用例

测试实现指导

前置准备

你需要用Mockito对RestTemplate进行打桩模拟,根据你的业务逻辑分支,分别模拟正常返回和抛出HttpStatusCodeException两种场景,验证对应分支的func方法是否被正确调用即可完成全量代码覆盖。
如果你的func1~func8是被测业务类自身的方法,需要对被测类使用@Spy注解,才能验证方法的调用情况;如果func是其他依赖类的方法,直接对对应依赖加@Mock注解即可。

分支覆盖梳理

你当前的逻辑一共包含8个可执行分支,逐个覆盖即可:

  • 正常返回+low优先级:调用func1
  • 正常返回+high优先级:调用func2
  • 抛出503异常+low优先级:调用func3
  • 抛出503异常+high优先级:调用func4
  • 抛出403异常+low优先级:调用func5
  • 抛出403异常+high优先级:调用func6
  • 抛出其他状态码异常+low优先级:调用func7
  • 抛出其他状态码异常+high优先级:调用func8

代码示例

测试类基础结构

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class 你的业务类名Test {
    @Mock
    private RestTemplate restTemplate;

    // 被测类用Spy注解才能验证自身方法的调用
    @Spy
    @InjectMocks
    private 你的业务类名 targetService;

    // 替换为你业务类中someendpoint的实际值
    private static final String TEST_ENDPOINT = "http://your-test-endpoint";
    private final Request mockRequest = new Request();
    private final HttpHeaders mockHeaders = new HttpHeaders();
}

正常返回场景用例

@Test
void 正常返回_low优先级_调用func1() {
    // 打桩RestTemplate返回正常响应
    ResponseEntity<Response> mockResp = ResponseEntity.ok(new Response());
    when(restTemplate.postForEntity(eq(TEST_ENDPOINT), any(HttpEntity.class), eq(Response.class)))
            .thenReturn(mockResp);

    // 执行测试方法
    targetService.processData(mockRequest, mockHeaders, "low");

    // 验证分支逻辑正确
    verify(targetService, times(1)).func1();
    verify(targetService, never()).func2();
}

@Test
void 正常返回_high优先级_调用func2() {
    ResponseEntity<Response> mockResp = ResponseEntity.ok(new Response());
    when(restTemplate.postForEntity(eq(TEST_ENDPOINT), any(HttpEntity.class), eq(Response.class)))
            .thenReturn(mockResp);

    targetService.processData(mockRequest, mockHeaders, "high");

    verify(targetService, times(1)).func2();
    verify(targetService, never()).func1();
}

异常返回场景用例

以503+low优先级为例,其他状态码的分支仅需修改异常的状态码返回值即可:

@Test
void 抛503异常_low优先级_调用func3() {
    // 模拟HttpStatusCodeException返回503状态码
    HttpStatusCodeException mockEx = mock(HttpStatusCodeException.class);
    when(mockEx.getStatusCode()).thenReturn(HttpStatus.SERVICE_UNAVAILABLE);

    // 打桩RestTemplate抛出异常
    when(restTemplate.postForEntity(eq(TEST_ENDPOINT), any(HttpEntity.class), eq(Response.class)))
            .thenThrow(mockEx);

    targetService.processData(mockRequest, mockHeaders, "low");

    verify(targetService, times(1)).func3();
}

其他状态码(非403、503)的场景需要额外模拟响应体,避免ObjectMapper解析失败:

@Test
void 抛404异常_high优先级_调用func8() throws JsonProcessingException {
    HttpStatusCodeException mockEx = mock(HttpStatusCodeException.class);
    when(mockEx.getStatusCode()).thenReturn(HttpStatus.NOT_FOUND);
    // 构造合法的响应JSON串
    String mockRespJson = new ObjectMapper().writeValueAsString(new Response());
    when(mockEx.getResponseBodyAsString()).thenReturn(mockRespJson);

    when(restTemplate.postForEntity(eq(TEST_ENDPOINT), any(HttpEntity.class), eq(Response.class)))
            .thenThrow(mockEx);

    targetService.processData(mockRequest, mockHeaders, "high");

    verify(targetService, times(1)).func8();
}

注意事项

  • 如果你的someendpoint是通过配置注入的字段,可以在测试类用@TestPropertySource注入测试值,保证打桩时的参数匹配正确
  • 如果func1~func8是私有方法,无需验证方法调用,改为验证方法执行后的业务副作用即可,比如是否修改了成员变量、是否调用了其他第三方依赖的方法
  • 测试异常分支的兜底逻辑时,必须模拟合法的响应体内容,否则readValue方法会抛出解析异常,导致测试失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 21:21:04