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");
我正在研究 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");