How do I mock RestTemplate exchange using junit 5 (Jupiter) - java

I tried with below code but in response body I got empty records.
Please help me on below code.
Java Code:
public Customer getCustomers(String customerId, String authorization) {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.set("Authorization", authorization);
HttpEntity<Customer> request = new HttpEntity<>(headers);
Map<String, Object> params = new HashMap<>();
params.put("CustomerId", customerId);
String url = "https://localhost:8080/api/customer/{CustomerId}/get";
ResponseEntity<Customer> response = restTemplate.exchange(
url,
HttpMethod.GET,
request,
Customer.class,
params
);
Customer customer = null;
if (response != null && response.getBody() != null) {
customer = response.getBody();
}
return customer;
}
Test Code:
#Test
public void testGetCustomersSuccess() {
Customer customer = new Customer();
customer.setCountryCode("countryCode");
customer.setCreatedFrom("createdFrom");
customer.setCustomerlandline("224153");
customer.setCustomermobile("1522252");
customer.setEmail("email");
customer.setFirstname("firstName");
customer.setFiscalCode("fiscalCode");
customer.setFirstname("lastName");
customer.setId("5");
MultiValueMap<String, String> headers=new LinkedMultiValueMap<>();
headers.set(Authorization,"12152");
ResponseEntity<Customer> response=new ResponseEntity<Customer>(HttpStatus.OK);
when(restTemplate.exchange(Mockito.any(String.class),
Mockito.<HttpMethod> any(),
Mockito.<HttpEntity<Customer>> any(),
Mockito.<Class<Customer>> any(),
Mockito.<String, Object> anyMap()))
.thenReturn(response);
assertEquals(response.getBody(),serviceClientImpl.getCustomers("5", "12152"));
}

You need to set the value of customer in your response.
The values you are setting in customer object is not being used anywhere.
Try this:
ResponseEntity<Customer> response=new ResponseEntity<Customer>(customer,HttpStatus.OK);

Related

How to fetch data from http response entity?

I am using SpringBoot to fetch access Token from my client. I could not separate the Access Token from the responseEntity. Is there a way to Fetch the AccessToken data alone?
Here is the code:
public ResponseEntity generate_Access_token() {
String url = "https://zoom.us/oauth/token";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
final Gson gson = new Gson();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("grant_type", "account_credentials");
map.add("client_id", "XXX");
map.add("client_secret", "XXX");
map.add("account_id", "XXX");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
//ResponseEntity<String> response_data=new ResponseEntity<String>(response.toString(), HttpStatus.CREATED);
ResponseEntity<AccessTokenResponse> response_data = restTemplate.postForEntity( url, request , AccessTokenResponse.class );
return response_data.getAccessToken();
}
class AccessTokenResponse{
#JsonProperty("access_token")
String accessToken;
//other props you are interested in
//+ getters/setters
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
}
The response:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiJlNDI1NDFkYi0zMTllLTRiMGYtOWIwMC04YTVlZmY4NTI2NTAifQ.eyJ2ZXIiOjcsImF1aWQiOiJjNWFjZThhNGRiNDY0NTJhM2YxNGNkZjcyZjY1MjU2NSIsImNvZGUiOiIxYldicXNVNVR3V1hDUEY5M2ZTbjdBR21xT1NKOXBUS0kiLCJpc3MiOiJ6bTpjaWQ6NjFtN2ppSXFUM2VMWDRuS0xZVUdGZyIsImdubyI6MCwidHlwZSI6MywiYXVkIjoiaHR0cHM6Ly9vYXV0aC56b29tLnVzIiwidWlkIjoianYwWWZyUDlRLWFLTlctTFVlSXRDZyIsIm5iZiI6MTY1NjMxNzM2MiwiZXhwIjoxNjU2MzIwOTYyLCJpYXQiOjE2NTYzMTczNjIsImFpZCI6IkJ4MnVOWHpHUWwtSHVDN3BITWF2NWciLCJqdGkiOiJlYTYwMDkwYS0wMWY1LTQwODctODgxMi0wNmQ2Mzk1NTI2ZGUifQ.nKiYXxCDbhQRsyR2pTu0nwegQKBHsSR9JT7CBnad5pPfBi4pVBISjGp6icRv2Nyv_L7lNzVBK8clW7Z5zM9TUg",
"token_type": "bearer",
"expires_in": 3599,
"scope": "meeting:read:admin user:master user:read:admin user:write:admin"
}
Make your life easier, not harder - use plain DTO
class AccessTokenResponse{
#JsonProperty("access_token");
String accessToken
//other props you are interested in
//+ getters/setters
}
and then
AccessTokenResponse response = restTemplate.postForObject( url, request , AccessTokenResponse.class );
response.getAccessToken(); //here you have it

Mock to POST HTTP request get null pointer exception

I have this method
public HTTPResult post(String url, String requestBody) throws Exception {
return HTTPPostPut(url, requestBody, HttpMethod.POST);
}
public HTTPResult HTTPPostPut(String url, String requestBody,HttpMethod httpMethod) throws Exception {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("content-type","application/json");
HttpEntity requestEntity = new HttpEntity(requestBody,headers);
try {
ResponseEntity<String> response = this.restTemplate.exchange(url, httpMethod, requestEntity, String.class);
return new HTTPResult((String) response.getBody(), response.getStatusCode().value());
} catch (ResourceAccessException var8) {
String responseBody = var8.getCause().getMessage();
JSONObject obj = new JSONObject(responseBody);
return new HTTPResult(obj.getString("responseBody"), Integer.parseInt(obj.getString("statusCode")));
}
}
Which I created for it mock and getting null pointer exception:
public void testPost() throws Exception{
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("content-type","application/json");
HttpEntity requestEntity = new HttpEntity("{blbl}",headers);
ResponseEntity<String> response = new ResponseEntity("{blbl}", HttpStatus.OK);
RestTemplate mockRestTemplate = mock(RestTemplate.class);
when(mockRestTemplate.exchange(baseUrl, HttpMethod.POST, requestEntity, String.class)).thenReturn(response);
RestAPI api = new RestAPI(mockRestTemplate);
HTTPResult res = null;
try {
res = api.post(baseUrl,"{blbl}");
} catch (IOException e) {
e.printStackTrace();
}
assertEquals(res.getResponseBody(), "{blbl}");
assertEquals(res.getStatusCode(), HttpStatus.OK.value());
}
I am getting null pointer exception when calling:
res = api.post(baseUrl,"{blbl}");
This is because the response is null.
Use an argument matcher when arranging the mock as the instance being passed to the mocked dependency is different to what is passed when the test is exercised.
This will cause the mock to return null response as expected instances do not match
Refactor the test
public void testPost() throws Exception {
//Arrange
String expected = "{blbl}";
ResponseEntity<String> response = new ResponseEntity(expected, HttpStatus.OK);
RestTemplate mockRestTemplate = mock(RestTemplate.class);
when(mockRestTemplate.exchange(eq(baseUrl), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class)))
.thenReturn(response);
RestAPI api = new RestAPI(mockRestTemplate);
//Act
HTTPResult res = api.post(baseUrl, expected);
//Assert
assertEquals(res.getResponseBody(), expected);
assertEquals(res.getStatusCode(), HttpStatus.OK.value());
}
Note the use of the any(HttpEntity.class) matcher which will allow the passed HttpEntity to be matched when invoked.
Since the use of argument matches is none or all, the eq() matcher is used for the remaining constant arguments.

Authorization for Google Drive Push Notifications for Java

I am trying to get push notifications from a resource on Google Drive to my server. I have been looking at this example:
https://developers.google.com/drive/v3/web/push
And I have tried translating that to Java into something like this:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "36d00d08-000d-4723-91bc-a1a6ec302e59");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
I have previously been using Googles libs for Drive to access files. In those cases I didn't need to create the request in such a "manual" way. I have used the class GoogleAuthorizationCodeFlow with a token to authorize my requests. I'm not sure how I should do that with RestTemplate. I am guessing that I need to do something like:
headers.set("Authorization", X);
What should X be here? Is that even the right way to approach authorization?
Edit:
Here is my attempt by reading a secret. The result is HTTP 401:
#Override
public String startListening() throws IOException {
final String fileId = "omitted";
String uri = "https://www.googleapis.com/drive/v3/files/" + fileId + "/watch";
HttpHeaders headers = getHeaders(getSecret());
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(getProperties(), headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
return response.getStatusCode() + " " + response.getBody() + " " + response.getHeaders();
}
private static HttpHeaders getHeaders(String theString) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + theString);
return headers;
}
private static MultiValueMap<String, String> getProperties() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("id", "some uid");
map.add("type", "web_hook");
map.add("address", "https://mydomain.appspot.com/rest/drive");
return map;
}
private static String getSecret() throws IOException {
InputStream in =
ConcreteDriveListenerFactory.class.getResourceAsStream("/drive_secret.json");
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer, "UTF-8");
return writer.toString();
}
As #DalmTo has mentioned, X is for token. With regard to sample POST request for Drive API try this code snippet from this SO thread. It also uses a POST method.
public static void main(String argv[]) throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.googleapis.com/drive/v2/files");
post.addHeader("Content-Type", "application/json");
post.addHeader("Authorization",
"Bearer XXXXXXXXXXXXXXXXXXXXXXXXX");
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", "Test folder");
jsonObject
.addProperty("mimeType", "application/vnd.google-apps.folder");
post.setEntity(new StringEntity(jsonObject.toString()));
httpClient.execute(post);
}

Restful Spring postForObject missing all property values

I try to simulate restful server:
private void btnPostActionPerformed(java.awt.event.ActionEvent evt) {
RestTemplate restTemplate = new RestTemplate();
Issuer issuer = new Issuer();
issuer.setCountry("Teacher 1");
issuer.setIssuerName("Department 1");
String url = txtHost.getText()+txtGet.getText();
restTemplate.postForObject(url, issuer, Issuer.class) ;
}
Controller code:
#RequestMapping(value = "/issuer/addIssuer", method = RequestMethod.POST)
#ResponseBody
public Issuer addIssuer(#ModelAttribute("issuer") Issuer issuer) {
if (issuer != null) {
logger.info("Inside addIssuer, adding: " + issuer.toString());
} else {
logger.info("Inside addIssuer...");
}
issuers.put(issuer.getTicker(), issuer);
return issuer;
}
I have fill some attributes, but when I debug the server, all values is null.
INFO : com.avaldes.tutorial.RestController - Inside addIssuer, adding: [null, null, null, null]
IssuerName and country is null too..
What is wrong with my code?
You are using #ModelAttribute in your controller. In that case you'll need to send your data as application/x-www-form-urlencoded:
MultiValueMap<String, Object> variables = new LinkedMultiValueMap<>();
variables.add("country", "Teacher 1");
variables.add("issuerName", "Department 1");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(variables, requestHeaders);
String url = txtHost.getText()+txtGet.getText();
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Issuer.class);

Spring restTemplate issue in getting response

My rest server is generating response when I called it with rest client software. When I call it with resttemplate code mentioned above, then server generates response(print logs) but resttemplate does nothing(no next line executes after call) and prints internal error.
This is the method in my server
#ResponseBody
public ResponseEntity<Map<String, Object>> name(){......
...
return new ResponseEntity<Map<String, Object>>(messagebody, HttpStatus.OK);
}
This is the way I am calling it through restTemplate
ResponseEntity<Map> response1 = restTemplate.getForEntity(finalUrl.toString(), Map.class);
Try to use ParameterizedTypeReference instead of wildcarded Map.
It should looks like this.
ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
ResponseEntity<Map<String, Object>> response = restTemplate.exchange(finalUrl.toString(), HttpMethod.GET, null, typeRef);
this is a example that works for me
#RequestMapping(value = "/getParametros/{instancia}", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> getParametros(#PathVariable String instancia)
{
LOG.debug("REST. Obteniendo parametros del servidor " + instancia);
Map<String, String> mapa = parametrosService.getProperties(instancia);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=UTF-8");
headers.add("X-Fsl-Location", "/");
headers.add("X-Fsl-Response-Code", "302");
ObjectMapper mapper = new ObjectMapper();
String s = "";
try
{
s = mapper.writeValueAsString(mapa);
} catch (JsonProcessingException e)
{
LOG.error("NO SE PUEDE MAPEAR A JSON");
}
if (mapa == null)
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<String>(s, headers, HttpStatus.OK);
}
you can Catch the HttpStatusCodeException from which you can get response in String .
below code works for me.
restTemplate.postForObject( url, jsonRequest, ResponseData.class );
catch( HttpStatusCodeException codeException )
{
String payload = codeException.getResponseBodyAsString();
System.out.println( payload );
}

Categories

Resources