I am working on Spring Boot project with microservice architecture. I have a service that is talking to another service via RestTemplate. HttpDataClient.java
class is sending dataId
to external service and should receive something in response. For my test I should test that RestTemplate and check if I am getting good response.
Here is class that I need to test:
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;
}
}
Test class looks like this:
@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));
}
}
When I run the test I am getting a 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)
What am I missing here?
At least these are wrong:
/game/idTest/
is different from /data/{0}
, they won't match but they need to in order for this to workSo your test method contents should be something like
// 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");