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

Mock RestTemplate返回Null问题排查与修复求助

解决RestTemplate Mock返回null导致的NullPointerException问题

错误信息

Cannot invoke "org.springframework.http.ResponseEntity.getBody()" because "response" is null
java.lang.NullPointerException: Cannot invoke "org.springframework.http.ResponseEntity.getBody()" because "response" is null

测试类代码

class UtilsControllerTest {

    @Mock
    RestTemplate restTemplate=mock(RestTemplate.class);
    @Test
    void checkPermission() {
        boolean permitted = true;

        ResponseEntity<PermissionResponseModel> response = ResponseEntity.ok(new PermissionResponseModel(permitted));

        when(restTemplate.postForEntity(any(String.class), any(Map.class), any(Class.class)))
                .thenReturn(response);

        UtilsController utilsController = new UtilsController();
        assertTrue(utilsController.checkPermission("69696969", Task.MAKE_REQUEST, restTemplate));
        verify(restTemplate, times(1)).postForEntity(any(), any(), any());
    }

}

UtilsController实现代码

public class UtilsController {
    private static final String authString = "Authorization";

    /**
     * Checks if the user is authorised to do a certain task.
     *
     * @param token the identification token
     * @param task  the task
     * @return true iff user is allowed, false otherwise
     */
    public boolean checkPermission(String token, Task task, RestTemplate restTemplate) {
        HttpHeaders authHeaders = new HttpHeaders();
        authHeaders.setContentType(MediaType.APPLICATION_JSON);
        authHeaders.set(authString, token);
        String url = "http://localhost:8081/permission";

        PermissionRequestModel prm = new PermissionRequestModel();
        prm.setTask(task);
        HttpEntity<PermissionResponseModel> entity = new HttpEntity(prm, authHeaders);

        ResponseEntity<PermissionResponseModel> response =
                restTemplate.postForEntity(url, entity, PermissionResponseModel.class);
        return response.getBody().isPermitted();
    }
}

问题原因

你的Mock配置参数和实际调用不匹配:测试中用any(Map.class)匹配请求体,但实际代码里传递的是HttpEntity对象,导致Mockito找不到对应的Stub,返回默认的null值。同时,测试类里@Mock注解和手动mock(RestTemplate.class)重复初始化,可能引发不必要的冲突。

修复方案

  1. 修正参数匹配规则:把any(Map.class)替换为any(HttpEntity.class),确保和实际调用的参数类型一致;
  2. 清理重复初始化:保留@Mock注解的同时,在测试类上添加Mockito扩展注解(JUnit5用@ExtendWith(MockitoExtension.class),JUnit4用@RunWith(MockitoJUnitRunner.class)),让Mockito自动初始化Mock对象。

修改后的测试类代码:

@ExtendWith(MockitoExtension.class)
class UtilsControllerTest {

    @Mock
    RestTemplate restTemplate;

    @Test
    void checkPermission() {
        boolean permitted = true;

        ResponseEntity<PermissionResponseModel> response = ResponseEntity.ok(new PermissionResponseModel(permitted));

        // 匹配实际传递的HttpEntity类型参数
        when(restTemplate.postForEntity(any(String.class), any(HttpEntity.class), eq(PermissionResponseModel.class)))
                .thenReturn(response);

        UtilsController utilsController = new UtilsController();
        assertTrue(utilsController.checkPermission("69696969", Task.MAKE_REQUEST, restTemplate));
        verify(restTemplate, times(1)).postForEntity(any(), any(), eq(PermissionResponseModel.class));
    }

}

额外提示

如果需要更精准的参数匹配,可以使用eq()指定具体参数值,或者用argThat()自定义匹配逻辑,确保Stub能准确命中实际调用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:35:21