Mockito doReturn throws Null Pointer Exception - java

I'm trying to mock a method call from class called RestClient in another called DiscoveryAdapter but as and when i'm trying to do a doReturn it throws a null pointer exception.
In test i'm trying to spy the restClient object in order to mock the method call in DiscoveryAdapter.discovery method but with it throws a null pointer exception when doReturn is called.
Please check the code below.
RestClient.class
#Component
#Scope("prototype")
public class RestClient {
private static final Logger logger = LoggerFactory.getLogger(RestClient.class);
private RestTemplate restTemplate = null;
private PoolingHttpClientConnectionManager syncConnectionManager;
public void init() {
restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(buildhttpClient()));
}
public String queryRestEndpoints(HereMapsImpl mapType,String basePath,boolean isSSl) {
URI uriObject = null;
String uriPath = mapType.returnUri();
init();
try {
uriObject = RestUtils.buildUriFromString(basePath, isSSl, uriPath);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("rest api is {}",uriObject);
//spring api
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> requestEntity = new HttpEntity<String>("",headers);
//rest api call with uriObject
ResponseEntity<String> responseEntity = restTemplate.exchange(uriObject,
HttpMethod.GET, requestEntity, String.class);
if(responseEntity.getStatusCodeValue() >=400 || responseEntity.getStatusCodeValue() <= 500)
logger.info("failed with status code {}",responseEntity.getStatusCodeValue() );
logger.info("checking my response");
logger.info("checking my response here {}",responseEntity.getBody());
return responseEntity.getBody();
}
private CloseableHttpClient buildhttpClient() {
CloseableHttpClient httpClient = null;
httpClient = HttpClientBuilder.create().setConnectionManager(getSyncConnectionManager())
.build();
return httpClient;
}
public PoolingHttpClientConnectionManager getSyncConnectionManager() {
syncConnectionManager = new PoolingHttpClientConnectionManager();
return syncConnectionManager;
}
DisoveryAdapter.class
#Component
public class DisoveryAdapter {
private static final Logger log = LoggerFactory.getLogger(DisoveryAdapter.class);
#Autowired
private RestClient restClient;
public void discovery() {
log.info("starting thread");
String response = restClient.queryRestEndpoints(eatDrink, completeUriPath, true);
log.info("oeat drink response {}",response);
}
}
DiscoveryAdapterTest.class
class HereMapsCheckImpTest {
private static final Logger log = LoggerFactory.getLogger(HereMapsCheckImpTest.class);
private RestClient restClient;
private HereMapsCheckImp hereMaps;
#Before
public void init() {
hereMaps = new HereMapsCheckImp();
restClient = new RestClient();
}
#Test
public void test() {
RestClient spyRestClient = spy(restClient);
log.info("with spring {}",spyRestClient);
doReturn("{\n" +
" color: \"red\",\n" +
" value: \"#f00\"\n" +
"}").when(spyRestClient).queryRestEndpoints(any(),any(),any());
hereMaps.discovery();
verify(spyRestClient).queryRestEndpoints(any(),any(),any());
}
}

Related

Google cloud function integration testing pass param?

I have created a cloud function to print greetings like "Hello David!". my function below:
public void service(HttpRequest request, HttpResponse response)
throws IOException {
String name = request.getFirstQueryParameter("name").orElse("world");
try {
JsonElement requestParsed = gson.fromJson(request.getReader(), JsonElement.class);
JsonObject requestJson = null;
if (requestParsed != null && requestParsed.isJsonObject()) {
requestJson = requestParsed.getAsJsonObject();
}
if (requestJson != null && requestJson.has("name")) {
name = requestJson.get("name").getAsString();
}
} catch (JsonParseException e) {
logger.severe("Error parsing JSON: " + e.getMessage());
}
var writer = new PrintWriter(response.getWriter());
writer.printf("Hello %s!", name);
}
I have written a integration test like below:
#BeforeEach
public void setUp() throws IOException {
String baseDir = System.getProperty("user.dir");
emulatorProcess = new ProcessBuilder()
.command("./../gradlew", "alo")
.directory(new File(baseDir))
.start();
}
#AfterEach
public void tearDown() throws IOException {
InputStream stdoutStream = emulatorProcess.getInputStream();
ByteArrayOutputStream stdoutBytes = new ByteArrayOutputStream();
stdoutBytes.write(stdoutStream.readNBytes(stdoutStream.available()));
System.out.println(stdoutBytes.toString(StandardCharsets.UTF_8));
if (emulatorProcess.isAlive()) {
emulatorProcess.destroy();
}
}
#Test
void helloHttp_shouldRunWithFunctionsFramework() throws Throwable {
String functionUrl = BASE_URL + "/helloHttp";
HttpRequest getRequest = HttpRequest.newBuilder().uri(URI.create(functionUrl)).GET().build();
RetryRegistry registry = RetryRegistry.of(RetryConfig.custom()
.maxAttempts(6)
.intervalFunction(IntervalFunction.ofExponentialBackoff(200, 2))
.retryExceptions(IOException.class)
.retryOnResult(body -> body.toString().length() == 0)
.build());
Retry retry = registry.retry("my");
String body = Retry.decorateCheckedSupplier(retry, () -> client.send(
getRequest,
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)).body()
).apply();
assertThat(body).isEqualTo("Hello world!");
}
So I want to fake a params name in the integration test to pass to my GCP function.
so in my GCP function I can take it like this: name = requestJson.get("name").getAsString();. How do I do it?
I just search it out and the answer is: add post method like this
HttpRequest getRequest = HttpRequest
.newBuilder()
.uri(URI.create(functionUrl))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"David\"}"))
.build();

How to get status for circuit breaker status with netflix hystrix?

This is my AppService Class, where I need to add logic for getting the status for the circuit breaker if it's open or closed but I am unable to find a way. Also, i have made use of ignoreExceptions but seems like trouble is there. Just new to coding and this feature and unable to get an appropriate answer. I am not sure how to use isCircuitBreakerOpen().
#Service
public class AppService {
private static final Logger LOG = LoggerFactory.getLogger(AppService.class);
private final RestTemplate restTemplate;
public AppService(RestTemplate rest) {
this.restTemplate = rest;
}
#HystrixCommand(fallbackMethod = "reliable", commandProperties= {
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "100"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "10000"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10")
})
public ResponseEntity<String> answerList() throws Exception {
return callingDownStreamService404();
}
#HystrixCommand(fallbackMethod = "reliable", commandProperties= {
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "100"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "10000"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10")
})
public ResponseEntity<String> answerList503() throws Exception {
return callingDownStreamService503();
}
private ResponseEntity<String> callingDownStreamService404() throws Exception {
URI uri = URI.create("http://localhost:8090/recommended/404");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<Object> entity = new HttpEntity<Object>(headers);
ResponseEntity<String> out = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
System.out.println("Application code : " + out.getStatusCode());
return out;
}
private ResponseEntity<String> callingDownStreamService503() throws Exception {
URI uri = URI.create("http://localhost:8090/recommended/503");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<Object> entity = new HttpEntity<Object>(headers);
ResponseEntity<String> out = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
System.out.println("Application code : " + out.getStatusCode());
if (out.getStatusCode().toString().startsWith("5")) {
throw new HystrixBadRequestException("bad request messageg");
}
return out;
}
#HystrixCommand(commandKey = "MyHystrixCommand",fallbackMethod = "myHystrixFallback", threadPoolKey = "ThreadPoolKey",commandProperties= {
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "100"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "10000"),
#HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10")},
ignoreExceptions = {HttpServerErrorException.class, HystrixBadRequestException.class, HttpClientErrorException.class})
public ResponseEntity<String> getServiceCallResponse(String serviceUrl, HttpEntity<?> entity) {
serviceUrl = "http://localhost:8090/recommended/500";
ResponseEntity<String> resp = null;
try {
System.out.println("Calling -----" + serviceUrl);
resp = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class);
}
catch(RestClientException e) {
System.out.println("Calling -----" + serviceUrl + "Exception is this" + e.getRootCause());
handleExceptionForHystrix("getServiceCallResponse", e);
}
return resp;
}
private void handleExceptionForHystrix(String function, Exception e) {
if (e instanceof HttpStatusCodeException) {
HttpStatus httpStatusCode = ((HttpStatusCodeException)e).getStatusCode();
if(httpStatusCode.equals(HttpStatus.BAD_REQUEST) || httpStatusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
throw new HystrixBadRequestException("Hystrix Bad Request Exception Occurred" + httpStatusCode, e);
}
throw new RuntimeException(function, e);
}
throw new RuntimeException(function, e);
}
public ResponseEntity<String> myHystrixFallback(String serviceUrl, HttpEntity<?> entity, Throwable hystrixCommandExp) {
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
}
#Recover()
public ResponseEntity<String> reliable() {
return new ResponseEntity<String>(
"The downstream application is unavailable and the circuit is open", HttpStatus.OK);
}
}
this is the main class where i have placed the endpoints. I am also making use of AppStore which is the downstream app and same enpoints are configured there.
#EnableHystrixDashboard
#EnableCircuitBreaker
#RestController
#SpringBootApplication
public class DavinciCircuitbreakerApplication {
#Autowired
private AppService appService;
#Bean
public RestTemplate rest(RestTemplateBuilder builder) {
return builder.build();
}
#RequestMapping("/to-answer/404")
public ResponseEntity<String> toAnswer() {
ResponseEntity<String> response = null;
try{
response = appService.answerList();
}catch(Exception e){
System.out.println("excpetion"+ e.getMessage());
return new ResponseEntity<String>("failure", HttpStatus.valueOf(500));
}
return response;
}
#RequestMapping("/to-answer/503")
public ResponseEntity<String> toAnswer503() {
ResponseEntity<String> response = null;
try{
response = appService.answerList503();
}catch(Exception e){
System.out.println("excpetion"+ e.getMessage());
return new ResponseEntity<String>("failure", HttpStatus.valueOf(503));
}
return response;
}
#RequestMapping("/to-answer/500")
public ResponseEntity<String> toAnswer500() {
ResponseEntity<String> response = null;
try{
response = appService.getServiceCallResponse(null, response);
}catch(Exception e){
System.out.println("excpetion"+ e.getMessage());
return new ResponseEntity<String>("Internal Server Error", HttpStatus.valueOf(500));
}
return response;
}
public static void main(String[] args) {
SpringApplication.run(DavinciCircuitbreakerApplication.class, args);
}
}
You can use HystrixCircuitBreaker.Factory.getInstance(...) to get instance of HystrixCommand. Refer to link for more details.
Further you can call isCircuitBreakerOpen() on this HystrixCommand instance.

calling request trigger url of azure logic app from RestTemplate java

I have Azure logic app with request trigger. I want to trigger this logic app from my java application. So, I am trying to call the request trigger url from my java API.
It is working fine if i am using DefaultHttpClient but getting 401 on calling it using RestTemplate in java.
DefaultHttpClient code:
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(
"{url of azure logic app trigger}");
//StringEntity input = new StringEntity("{\"qty\":100,\"name\":\"iPad 4\"}");
//input.setContentType("application/json");
//postRequest.setEntity(input);
HttpResponse response = httpClient.execute(getRequest);
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
httpClient.getConnectionManager().shutdown();
return("Success");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return("Error");
} catch (UnsupportedOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return("Error");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return("Error");
}
RestTemplate Code
#Service
public class SampleService {
#Autowired HttpClientService<String, String> httpClientService;
public String callURL() {
ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() {
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
System.out.print(response.toString());
return false;
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
// TODO Auto-generated method stub
}
};
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString("{logic app url}")
// Add query parameter
.queryParam("api-version", {api-version})
.queryParam("sp", {sp})
.queryParam("sv", {sv})
.queryParam("sig",{sig});
RequestDetailsDAO requestDetails = new RequestDetailsDAO(builder.build().toUri().toString(), HttpMethod.GET);
String response = httpClientService.execute(requestDetails, null, responseErrorHandler, String.class);
return response.toString();
HttpClientService.java
#Service
public class HttpClientService<T, V> {
public RestTemplate restTemplate;
public HttpClientService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.setConnectTimeout(Duration.ofSeconds(5)).setReadTimeout(Duration.ofSeconds(5)).build();
}
public V execute(RequestDetailsDAO requestDetails, HttpEntity<T> entity, ResponseErrorHandler errorHandler,
Class<V> genericClass) {
restTemplate.setErrorHandler(errorHandler);
ResponseEntity<V> response = restTemplate.exchange(requestDetails.getUrl(), requestDetails.getRequestType(), entity, genericClass);
return response.getBody();
}
}
RequestDetailsDAO.java
public class RequestDetailsDAO {
private String url;
private HttpMethod requestType;
public RequestDetailsDAO(String url, HttpMethod requestTyp) {
super();
this.url = url;
this.requestType = requestTyp;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public HttpMethod getRequestType() {
return requestType;
}
public void setRequestType(HttpMethod requestType) {
this.requestType = requestType;
}
#Override
public String toString() {
return "RequestDetails [url=" + url + ", requestType=" + requestType + "]";
}
}
So, it seems that there's nothing special about LogicApps being called using RestTemplate.
It's just that RestTemplate by default URL encode the Uri given in parameter, and DefaultHttpClient does not - reference: apache vs resttemplate
In case of LogicApp URL, there is this "sp" parameter which is already URL endcoded, when you copy it from LogicApp -
"%2Ftriggers%2Fmanual%2Frun", so you need to decode that and pass "/triggers/manual/run" to UriComponentsBuilder. And then it works.
My code:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> request = new HttpEntity<>(requestDto, headers);
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString("https://prod-123901.westeurope.logic.azure.com:443/workflows/<workflow_id>/triggers/manual/paths/invoke")
.queryParam("api-version", "2016-10-01")
.queryParam("sp", "/triggers/manual/run")
.queryParam("sv", "1.0")
.queryParam("sig", "<your_sig>");
restTemplate.exchange(builder.build().toUri().toString(), HttpMethod.POST, request, Void.class);
update:
requestDto here is your custom dto object that goes in HTTP Body, like for example object of class:
public class RequestDto {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Please try with the simple standalone code with RestTemplate and check. I provide below small snippet.
try {
ResponseEntity<ResponseVO> response = restTemplate.exchange({uri of azure logic app trigger}, HttpMethod.GET, request, ResponseVO.class);
} catch (HttpStatusCodeException ex) {
int statusCode = ex.getStatusCode().value();
System.out.println("Status Code :"+statusCode);
ResponseEntity<?> resEntity = ResponseEntity.status(ex.getRawStatusCode()).headers(ex.getResponseHeaders())
.body(ex.getResponseBodyAsString())
}
Here ResponseVO.class is the Response to be mapped to an object, in this case, you can set your own class. In this catch block, you can find the exception details.

java - unit testing for REST request

I have the method:
public HTTPResult get(String url) throws Exception{
try {
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
return new HTTPResult(response.getBody(), response.getStatusCode().value());
}
catch (ResourceAccessException e) {
String responseBody = e.getCause().getMessage();
JSONObject obj = new JSONObject(responseBody);
return new HTTPResult(obj.getString("responseBody"), Integer.parseInt(obj.getString("statusCode")));
}
}
I want to do unit testing for it and i am not sure how to proceed:
public class MockHttpServerTest {
private static final int PORT = 51234;
private static final String baseUrl = "http://localhost:" + PORT;
private MockHttpServer server;
private SimpleHttpResponseProvider responseProvider;
private HttpClient client;
#Before
public void setUp() throws Exception {
responseProvider = new SimpleHttpResponseProvider();
server = new MockHttpServer(PORT, responseProvider);
server.start();
client = new DefaultHttpClient();
}
I am getting RED for MockHttpServer & SimpleHttpResponseProvider which should be part of org.apache.wink.client.*; which i am importing. so why do i have red ones? is there some simple way to unit test it?
HTTPResult return me response code and message.

Getting null in Environment variable

#Configuration
public class CustomRemoteTokenService implements ResourceServerTokenServices {
private static final Logger logger = LoggerFactory.getLogger(CustomRemoteTokenService.class);
#Resource
Environment environment;
private RestOperations restTemplate;
private String checkTokenEndpointUrl;
private String clientId;
private String clientSecret;
private String tokenName = "token";
private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
#Autowired
public CustomRemoteTokenService() {
restTemplate = new RestTemplate();
((RestTemplate) restTemplate).setErrorHandler(new DefaultResponseErrorHandler() {
#Override
// Ignore 400
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getRawStatusCode() != 400
&& response.getRawStatusCode() != 403 /* && response.getRawStatusCode() != 401 */) {
super.handleError(response);
}
}
});
}
public void setRestTemplate(RestOperations restTemplate) {
this.restTemplate = restTemplate;
}
public void setCheckTokenEndpointUrl(String checkTokenEndpointUrl) {
this.checkTokenEndpointUrl = checkTokenEndpointUrl;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) {
this.tokenConverter = accessTokenConverter;
}
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
#Override
public OAuth2Authentication loadAuthentication(String accessToken)
throws AuthenticationException, InvalidTokenException, GenericException {
/*
* This code needs to be more dynamic. Every time an API is added we have to add
* its entry in the if check for now. Should be changed later.
*/
HttpServletRequest request = Context.getCurrentInstance().getRequest();
MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
formData.add(tokenName, accessToken);
formData.add("api", environment.getProperty("resource.api"));
/* formData.add("api", "5b64018880999103244f1fdd");*/
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret));
Map<String, Object> map = null;
try {
map = postForMap(checkTokenEndpointUrl, formData, headers);
} catch (ResourceAccessException e) {
logger.error("Socket Exception occured at " + System.currentTimeMillis() + "for client_id : " + clientId);
GenericException ge = new GenericException(
"Could not validate your access token. If this occurs too often please contact MapmyIndia support at apisupport#mapmyindia.com");
ge.setHttpErrorCode(504);
ge.setOauthError("Access Token validation failed");
throw ge;
}
if (map.containsKey("error")) {
logger.error("check_token returned error: " + map.get("error") + " for client id : " + clientId);
String temp = map.get("error").toString();
GenericException ge = new GenericException(map.get("error_description").toString());
ge.setHttpErrorCode(Integer.parseInt(map.get("responsecode").toString()));
ge.setOauthError(temp);
switch (temp) {
case "invalid_token":
throw new InvalidTokenException(accessToken);
default:
throw ge;
}
}
Assert.state(map.containsKey("client_id"), "Client id must be present in response from auth server");
return tokenConverter.extractAuthentication(map);
}
#Override
public OAuth2AccessToken readAccessToken(String accessToken) {
throw new UnsupportedOperationException("Not supported: read access token");
}
private String getAuthorizationHeader(String clientId, String clientSecret) {
String creds = String.format("%s:%s", clientId, clientSecret);
try {
return "Basic " + new String(Base64.encode(creds.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Could not convert String");
}
}
private Map<String, Object> postForMap(String path, MultiValueMap<String, String> formData, HttpHeaders headers)
throws RestClientException {
if (headers.getContentType() == null) {
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
}
#SuppressWarnings("rawtypes")
Map map = restTemplate.exchange(path, HttpMethod.POST,
new HttpEntity<MultiValueMap<String, String>>(formData, headers), Map.class).getBody();
#SuppressWarnings("unchecked")
Map<String, Object> result = map;
return result;
}
}
I autowired Environment and getting null when I do environment.getProperty("resource.api");
It is always returning null but in another classes I autowire Environment and successfully retrieve the value from properties.
You have to take this steps :
1.Register a Properties
You need to register you properties file by #PropertySource("classpath:foo.properties") as :
#Configuration
#PropertySource("classpath:foo.properties")
public class CustomRemoteTokenService implements ResourceServerTokenServices {
//...
}
2.Injecting Properties
To obtain the value of a property with the Environment API:
#Autowired
private Environment env;

Categories