How to mock CompletableFuture in mockito - spring-boot

HttpEntity request = new HttpEntity(headers);
CompletableFuture<JsonNode> requestCompletableFuture = CompletableFuture
.supplyAsync(() -> restTemplate.exchange(baseUrl, HttpMethod.GET, request, JsonNode.class))
.thenApply((responseFutures) -> {
return responseFutures.getBody();
});
JsonNode response= requestCompletableFuture.get();
i am trying to mock completable future but it giving not expected response

Related

How to add file as Form data in Http request in spring boot

I'm writing test cases to a controller in spring boot which takes MultipartFile as RequestParam. In the test case method I'm using TestRestTemplate.exchange() to send the request to the controller. I'm not sure how to make the Headers correctly so that I can send the request.
The Postman curl looks like this:
curl --location --request POST 'localhost:9091/response/upload'
--form 'file=#"/home/adityak/Downloads/ClientLog_NEW.txt"'
For file uploading to any service or endpoint
private String testExchange(File file) {
//add file
LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("file", new FileSystemResource(file));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
new HttpEntity<>(params, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
"/upload-file",
HttpMethod.POST,
requestEntity,
String.class);
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode == HttpStatus.ACCEPTED) {
result = responseEntity.getBody();
}
return result;
}

Spring webclient exchangeToFlux() not making HTTP request

I'm using Spring WebFlux 5.3.6's WebClient to stream a response from a REST endpoint that generates text/csv content.
I can use retrieve() and responseSpec.bodyToFlux to stream the body only like this:
WebClient.ResponseSpec responseSpec = headersSpec.retrieve();
Flux<DataBuffer> dataBufferFlux = responseSpec.bodyToFlux(DataBuffer.class);
DataBufferUtils
.write(dataBufferFlux, outputStream)
.blockLast(Duration.of(20, ChronoUnit.SECONDS));
but I want to get hold of the content-type header and validate it as part of the test. The above code provides access to the response body only, and not the headers.
I've tried to instead use exchangeToFlux() to get more control, and access to the response headers, but what I'm seeing is that the HTTP request is never made. If I add a breakpoint to myResponse.setStatus(clientResponse.rawStatusCode()); it is never hit.
A fuller code sample is below. I've struggled to find any examples of exchangeToFlux that use DataBuffer to stream the result back.
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.responseTimeout(Duration.ofMillis(5000))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)));
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
WebClient.RequestHeadersSpec<?> headersSpec = webClient
.get()
.uri("http://localhost:8080/v1/users")
.header(CONTENT_TYPE, "text/csv");
MyResponse<T> myResponse = new MyResponse<>();
CountDownLatch latch = new CountDownLatch(1);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
headersSpec.exchangeToFlux(clientResponse -> {
// Never enters here!
myResponse.setStatus(clientResponse.rawStatusCode());
myResponse.setContentType(clientResponse.headers().contentType());
latch.countDown();
if (clientResponse.statusCode() == HttpStatus.OK) {
Flux<DataBuffer> dataBufferFlux = clientResponse.bodyToFlux(DataBuffer.class);
DataBufferUtils
.write(dataBufferFlux, outputStream)
.blockLast(Duration.of(20, ChronoUnit.SECONDS));
return dataBufferFlux;
}
return Flux.empty();
});
latch.await();
return myResponse;
Seem's like you are not subscribing to the Flux returned from headersSpec.exchangeToFlux.
headersSpec.exchangeToFlux(clientResponse -> {
// Never enters here!
myResponse.setStatus(clientResponse.rawStatusCode());
myResponse.setContentType(clientResponse.headers().contentType());
latch.countDown();
if (clientResponse.statusCode() == HttpStatus.OK) {
Flux<DataBuffer> dataBufferFlux = clientResponse.bodyToFlux(DataBuffer.class);
DataBufferUtils
.write(dataBufferFlux, outputStream)
.blockLast(Duration.of(20, ChronoUnit.SECONDS));
return dataBufferFlux;
}
return Flux.empty();
})
.subscribe(); // <- Subscribe is missing.

spring Rest APIcall working fine locally but failing on production

I have a rest endpoint http://abc-xyz.doamin.com.au:8443/myapplication/v2/test I consume this in my program which is working fine locally but failing in production
Exception
"message":"HTTP exception while calling TnDM",
"logger_name":"com.myapp.resource.MyResource",
"thread_name":"http-nio-8080-exec-7",
"level":"ERROR",
"level_value":40000,
"stack_trace":"org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error\n\t
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:89)\n\t
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:708)\n\t
at
locally works fine with 200 OK
{
"text": "Hello_Message"
}
Code
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HelloWorldRequest req = new HelloWorldRequest();
request.setName("myName");
HttpEntity entity = new HttpEntity(req, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
Create a pojo to cature the response type you have mentioned above:
public class Response
{
private String text;
//getter, setter
}
Then change this line:
ResponseEntity response = restTemplate.exchange(url,
HttpMethod.POST, entity, String.class);
with this:
ResponseEntity<Response> response = restTemplate.exchange(url, HttpMethod.POST, entity, Response.class);
Hope, this will work!

Passing RequestParam data to Spring RestController

I am using restTemplate.exchangemethod to invoke one service from another service.My request url does accept a request parameter.
url is of the formhttp://localhost:8035/sgapp/student/fetchDeptNo?sid
In the conttroller it is written as
#RestController
#RequestMapping(value="/sgapp/student")
public class SiController{
#GetMapping(value = "/fetchDeptNo",consumes = "application/x-www-form-urlencoded")
public ResponseEntity<String> getSid(#RequestParam(name = "sid")String sid){
String sid = myRepo.getSidCode(sid);
System.out.println("sid received from DB::"+sid);
return new ResponseEntity<String>(sid,HttpStatus.OK);
}
}
In the caller application I am invoking it as
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<?> entity = new HttpEntity<>(headers);
Map paramMap = new HashMap<String, String>();
paramMap.put("sid", sidData);
HttpEntity<String> sidRespnse = restTemplate.exchange(
"http://localhost:8035/sgapp/student/fetchDeptNo", HttpMethod.GET, entity, String.class,
paramMap);
But I'm getting folllowing exception:
org.springframework.web.client.HttpClientErrorException: 400 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
Can anyone provide any suitable solution to this???
That particular exchange method is used to substitute variables into the path.
If you want to pass query parameters, use UriComponentsBuilder to create the URL with query params:
UriComponentsBuilder builder =
UriComponentsBuilder
.fromHttpUrl(rootUri)
.queryParam("sid", sidData);
Then you can use RestTemplate as follows:
restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class);

Rest Template giving 400 Bad Request error

I am trying to make a REST call using Springs RestTemplate but I keep getting the HTTP response status 400 (bad request).
Can anyone please help on this?
RestTemplate transactiontemplate = new RestTemplate();
HttpHeaders transactionheaders = new HttpHeaders();
transactionheaders.add("Authorization", "Bearer "+AccessToken);
transactionheaders.add("Accept", "application/json");
transactionheaders.add("Accept-Encoding", "application/gzip");
transactionheaders.add("Content-Type", "application/json");
ObjectMapper mapper = new ObjectMapper();
//System.out.println(mapper.writeValueAsString(transaction));
HttpEntity<TransactionRequestDTO> transactionEntity = new
HttpEntity<TransactionRequestDTO> (transaction, transactionheaders);
ResponseEntity<String> transactionresponse = transactiontemplate.exchange(LocationUrl+"/"+locationId+"/transactions",
HttpMethod.POST, transactionEntity, String.class);
//String answer = transactiontemplate.postForObject(LocationUrl+"/"+locationId+"/transactions", transactionEntity, String.class);
//System.out.println(answer);
ObjectMapper transactionmapper = new ObjectMapper();
TransactionResponseDTO transactionResponseObject = transactionmapper.readValue(transactionresponse.getBody(), TransactionResponseDTO.class);
return transactionResponseObject;

Resources