Error: java.lang.NullPointerException by RestTemplate exchange method - SpringBoot

Error: java.lang.NullPointerException by RestTemplate exchange method - SpringBoot

我正在研究 Spring 具有微服务架构的引导项目。我有一个服务正在通过 RestTemplate 与另一个服务对话。 HttpDataClient.java class 正在向外部服务发送 dataId 并且应该会收到一些响应。对于我的测试,我应该测试 RestTemplate 并检查我是否得到良好的响应。

这是我需要测试的class:

  public class HttpDataClient implements DataClient{
    
        private final static Logger LOGGER = LoggerFactory.getLogger(HttpDataClient.class);
    
        private final RestTemplate restTemplate;
        private final ObjectMapper objectMapper = new ObjectMapper();
    
        public HttpDataClient(RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
        }
    
        @Override
        public DataResponse getData(String dataId) {
            try{
                JsonNode node = restTemplate.exchange(
                        String.format("/data/{0}", dataId),
                        HttpMethod.POST,
                        new HttpEntity<>(buildRequest(dataId), headers()),
                        JsonNode.class
                ).getBody();
                return dataResponse(node);
            }catch (HttpStatusCodeException e) {
                String msg = String.format(
                        "Error getting data for dataId: {0}",
                        dataId,
                        e.getStatusCode(),
                        e.getResponseBodyAsString());
                LOGGER.error(msg);
                return dataResponse.failed();
            }
        }
    
        private MultiValueMap<String, String> headers() {
            final LinkedMultiValueMap<String, String> mv = new LinkedMultiValueMap<>();
            mv.set(HttpHeaders.CONTENT_TYPE, "application/json");
            return mv;
        }
    
        private DataResponse dataResponse(JsonNode node) {
            return DataResponse.dataResponse(
                    asString(node, "dataId"),
                    asString(node, "author"),
                    asString(node, "authorDataId"),
                    asString(node, "serverSideDataId")
            );
        }
    
        private JsonNode buildRequest(String dataId) {
            ObjectNode root = objectMapper.createObjectNode();
            root.put("dataId", dataId);
            return root;
        }
    }

测试 class 看起来像这样:

@RunWith(MockitoJUnitRunner.class)
public class HttpDataServiceTest {

    @Mock
    RestTemplate restTemplate;

    @InjectMocks
    private HttpDataService httpDataService;

    @Test
    public void getData() {

        httpDataService.getData("gameIdTest");
        Mockito
            .when(restTemplate.exchange(
                    ArgumentMatchers.eq("/game/IdTest"),
                    ArgumentMatchers.eq(HttpMethod.POST),
                    ArgumentMatchers.any(),
                    ArgumentMatchers.<Class<DataResponse>>any()))
            .thenReturn(new ResponseEntity<>(HttpStatus.ACCEPTED));
    }
}

当我 运行 测试时我得到一个 NullPointerException

java.lang.NullPointerException at com.example.gamedata.HttpDataService.getData(HttpDataService.java:37) at com.example.data.HttpDataServiceTest.getData(HttpDataServiceTest.java:36) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

我在这里错过了什么?

至少这些是错误的:

  • 您需要在 调用实际方法之前 Mockito.when() 执行一些操作 。不在之后。
  • /game/idTest//data/{0} 不同,它们不匹配,但需要匹配才能正常工作
  • DataResponse 不是 JsonNode,它们也应该匹配
  • 在您的 when() 调用中,您实际上需要 return 在 HTTP 主体中接收一些合理的内容,仅“已接受”是不够的,它会使响应主体为空
  • 您需要提供一个合理的 json 节点作为响应

所以你的测试方法内容应该是这样的

    // create response object
    ObjectNode responseNode = JsonNodeFactory.instance.objectNode();
    responseNode.put("dataId", "");
    responseNode.put("author", "");
    responseNode.put("authorDataId", "");
    responseNode.put("serverSideDataId", "");
    
    // prepare your mock for the call
    Mockito
        .when(restTemplate.exchange(
                ArgumentMatchers.eq("/data/gameIdTest"),
                ArgumentMatchers.eq(HttpMethod.POST),
                ArgumentMatchers.any(),
                ArgumentMatchers.<Class<JsonNode>>any()))
        .thenReturn(new ResponseEntity<>(responseNode, HttpStatus.OK));

    // do the call
    httpDataService.getData("gameIdTest");