try {
response = restTemplate.postForEntity(endPoint, request, Object.class);
lOGGER.info("response is " + response);
} catch (Exception e) {
lOGGER.error("Exception :" + e.getMessage());
if ((e.getMessage().contains("401") || e.getMessage().contains("Unauthorized")) ) {
ServiceImpl.evictTokenCache("authToken");
getData(requestDto);
} else {
throw new CustomException(e.getMessage());
}
above is my service and trying to write test case for catch clause,and my test case is
#Test()
public void getExceptionTest() throws Exception {
RequestDto requestDto = new RequestDto();
requestDto.setPage("1");
AuthConfig authDTO = new AuthConfig();
authDTO.setUrl("Url");
Mockito.when(restTemplate.postForEntity(Mockito.anyString(), Mockito.any(), Mockito.any())).thenThrow((new Exception("Unauthorized")));
ResponseDTO response = restCallUtil.getData(requestDto);
assertNull(response);
}
what i am trying to do incatch block is,when ever i get Unauthorized exception i am clearing the cache and calling the same method again. So in order to test catch block from my test class i am trying to throw exception with message as "Unauthorized ",but when i run test case i am getting
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception: Unauthorized
The first thing to note is that an instance of Exception which is not also an instance of RuntimeException is a checked exception. Thus, the only way the for a method to throw a generic Exception is for the method signature to contain "throws Exception" or "throws Throwable".
So.. why are you getting this error? You are stubbing the postForEntity method which throws RestClientException, and Exception is not an instance of RestClientException. Thus, your stubbing is invalid.
If you want to stub the method such that the catch block for the generic case is entered, you will need to throw a RuntimeException, which is unchecked, and therefore not subject to the "throws" restriction.
That said, it would be probably be wiser to simply catch only the RestClientException in the original method. If there is some RuntimeException you want to catch, then you would hopefully already be aware of what that is and catch it specifically.
Related
I have Jenkins plugin written in Java. I am capturing all the workflows of execution of plugin in a integer variable in three ways 0(2xx workflows), 1(4xx workflows), 2(5xx workflows) and sending them to SignalFX for metrics. Since this is not an API and errors will be mainly caught in try catch workflow.
I wanted to ask how to read error codes from exception class and categorize them in 2xx, 4xx or 5xx. Are there some rules which I can follow by?
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException e) {
sendToSignalFX(0,data); // 0 means successful state
}
Some of the exceptions classes I will be using are -
Exception, IOException, InterruptedException, ParserConfigurationException, SAXException
I believe you may have to add a method to identify the failure reason from e.getMessage() for one OR have a custom exception to help with your case.
Also if it’s an HTTP request-related exception (from the error response code mentioned in the question details) or something, you may want to add a custom exception, instead of throwing the original exception. In the custom exception, you can add a custom field to get errorCode from the response code.
// MyCustomException.java
public class MyCustomException extends Exception {
String errorReason;
int errorCode;
public MyCustomException(Throwable throwable, String errorReason, int errorCode) {
super(errorReason, throwable);
this.errorReason = errorReason;
this.errorCode = errorCode;
}
}
And in your request handler code:
try {
// otherCode which might cause IOException
// ...
Response response = myHttpRequest();
if (!response.isSuccessful()) {
// identify the error code and set corresponding errorCode to MyCustomException. errorCode
int errorCode = 0;
// parse response.getStatusCode() or equivalent of the library and reassign the value of errorCode
throw new MyCustomException(e, e.getMessage(), errorCode);
}
// ...
// otherCode which might cause IOException
} catch (Exception | IOException e) {
throw new MyCustomException(e, e.getMessage(), 0);
}
I have a program in which I want to throw one of 4 exceptions that I define.
I get an HTTP response and according its error code I want to throw the exceptions:
Here is an example:
public List<Map<String, Object>> getData(String product) {
try {
Response<DataGeneralResponse> response = dataApi.dataGet(product).execute();
if (!response.isSuccessful()) {
log.error(String.format("Failed to get data for product [%s] error [%s]",
product,
Util.getErrorMsg(response)));
}
DataGeneralResponse body = response.body();
return body != null ? body.getData(): null;
} catch (Exception e) {
log.error(String.format("Failed to get data for product [%s] error[%s]",
product,
Util.getErrorMsg(response)));
}
return null;
}
So I need to to something like that in Util:
public void handleResponse(Response<DataGeneralResponse> response) throws CustomException {
switch (response.code()) {
case 500: throw new FirstCustomException(");
break;
case 404: throw new SecondCustomException(");
break;
default: throw new UnknownCustomException(");
}
}
But when I try to remove the catch clause I get unhandled IOException error on the execute method and on the getErrorMsg method.
Can someone help please?
I get unhandled IOException error on the execute method and on the getErrorMsg method.
This indicates that you have a method, which is trying to throw a checked exception, which is not surrounded by a try catch clause. By Java language standard all methods, which throw checked exceptions must do one of the two ..
Be surrounded by a try-catch block which catches the relevant exception
Declare that they throw the relevant exception by using the throws keyword
You can use one of the methods above to deal with error you are getting.
If this does not completely solve your problem, please add a comment below and I'll respond.
I am trying to write test for my controller with the code below. I want to cover the test for the code in the catch block statement but I'm not able to write one. I want to return a Server Response with failure code and message in the catch block.
#PostMapping(COUNTERS)
public ResponseEntity<?> getCounters(#Valid #RequestBody ApartmentCounterListRequest requestData) {
try {
log.debug("Entering API for counter list");
ApartmentCounterListResponse apartmentCounterListResponse = counterService.getAllCounters();
return ResponseEntity.ok(apartmentCounterListResponse);
} catch (Exception exception) {
log.error("Exception in counter list :: ", exception);
ServerResponse serverResponse = ResponseBuilder.buildVendorFailureMessage(new ServerResponse(),
RequestResponseCode.EXCEPTION);
return ResponseEntity.ok(JsonResponseBuilder.enquiryResponse(serverResponse));
}
}
My test code is as follows:
#Test
#DisplayName("Should return ServerResponse with failure data.")
void Should_Return_Server_Response_On_Exception() throws Exception {
/*given*/
ApartmentCounterListRequest apartmentCounterListRequest = ApartmentTestUtil.getApartmentCounterListRequest.
apply("test", "test");
Mockito.when(counterServic.getAllCounters()).thenThrow(new Exception());
// ServerResponse serverResponse = ApartmentTestUtil.getServerExceptionServerResponse.get();
/*then*/
mockMvc.perform(
post(COUNTER_URL)
.contentType(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(apartmentCounterListRequest)))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.resultCode", Matchers.is("-6")));
verify(counterService, times(1)).getAllCounters();
}
When I run this test I am getting the following error:
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception
I have gone through some of the following posts but haven't found a suitable answer yet.
Unit testing code in catch block of a Spring Controller
Java - How to Test Catch Block?
Unit testing code in catch block of a Spring Controller
JUnit for both try and catch block coverage
Can anyone help me write test that covers the catch block or tell me the way to do it?
I have this try catch in my controller to handle any unexpected exceptions. And for different api's I have to send a response with different response code and messages which doesnot allow me to use Exception handler.
The method you are mocking does not declare a checked exception, therefore Mockito is not able to throw one from there. Try to have the mock throw an unchecked exception (i.e. RuntimeException).
You can try to use willAnswer
Mockito.when(counterServic.getAllCounters()).thenAnswer(x -> {throw new Exception() });
Maybe this is a bit misused as Answer is used for more complex for when return
I have this code where I'm catching some exception and throwing a custom exception instead.
#Override
public void config() throws CustomException{
File jsonFile = new File("config.json");
try {
ConfigMapper config = mapper.readValue(jsonFile, ConfigMapper.class);
try {
this.instanceId = Integer.parseInt(config.getConfig().getClientId());
this.configParams = config.getConfig().getConfigParams();
} catch (NumberFormatException ex) {
throw new CustomException("Please provide a valid integer for instance ID", ex);
//LOGGER.log(Level.SEVERE, "error initializing instanceId. Should be an integer " + e);
}
} catch (IOException ex) {
throw new CustomException("Error trying to read/write", ex);
// LOGGER.log(Level.SEVERE, "IOException while processing the received init config params", e);
}
}
I need to write a unit test for this and below is how I wrote it.
#Test
public void should_throw_exception_when_invalid_integer_is_given_for_instanceID(){
boolean isExceptionThrown = false;
try{
Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
barcodeScannerServiceMock.config();
} catch (CustomException ex) {
isExceptionThrown = true;
}
assertTrue(isExceptionThrown);
}
But its throwing a number format exception and not the CustomException as I want it to be. But this makes sense as I'm using the mock object to throw the exception as a result of which my code logic is not executed. But if that's the case, how do I test this scenario? Please advice.
1.) Remove the line Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
2.) Change the Client-ID in your JSON-File to something that cannot be converted to an Integer.
this.instanceId = Integer.parseInt(config.getConfig().getClientId()); will fail due to that and thus throw an exception.
One advice regarding names: The name of your test method should be what's written in the Java-Doc. Just name it "testCustomException" & explain the methods function in the Java-Documentation. There are Naming-Conventions in Java (click here) which are basically general guidelines.
Practicing these is very helpful as it allows you to quickly get into your code again after not working on it for a month or so due to the increased readability.
This is my Exception:
public class MyException extends Exception {
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
Now immagine the next scenario, the code is way too long to paste here:
1 I got a Presentation class made in Swing in Presentation package
2 In package calculations I made simple operations with few numbers from received database fields
3 In package connections I got the database connections
Trouble comes here:
-In presentation layer I catch all errors, like this:
try {
//here is a method called updateCombo() wich throws:
//throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
} catch (MyException ex) {
try {
//Here we process error code, if error is not defined, uses default errors.
processCode(ex);
} catch (MyException ex1) {
Logger.getLogger(Presentacion.class.getName()).log(Level.SEVERE, null, ex1);
}
}
processCode is a simple list with cases, like this:
private void processCode(MyException e) throws MyException {
switch (e.getErrorCode()) {
case "ERROR_UPDATING_COMBO_BOX":
lblErrorText.setText("Error updating combo.");
throw e;
case "ERROR_SELECTING_PRIMARY_KEY":
lblErrorText.setText("Error selecting PK");
throw e;
case "ERROR_OPENING_CONNECTION":
lblErrorText.setText("Error opening connection.");
throw e;
default:
lblErrorText.setText("Excepcion not defined: "+ e.getMessage());
e.printStackTrace();
}
This is the scenario, the connection fails in 3rd package and leads to this:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
As I said, the error is thrown to the upper layer with throws clause in method header, this beeing 2nd package.
2nd package also throws a new exception to Presentation, because of failing connection:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
Presentation methods also throw this exception becase 2nd layer failed:
throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
The main problem:
Using debug i found out that the program does what it has to do. It gets to the connection layer and does this successfully:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
But, in 2nd layer, calculations, if connection fails it throws a new exception:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
This is the problem:
throw new
throwing new exception overrides ERROR_OPENING_CONNECTION with ERROR_SELECTING_PRIMARY_KEY. When it gets to presentation due to its "throw new" overrides ERROR_SELECTING_PRIMARY_KEY with ERROR_UPDATING_COMBO_BOX, resulting in the final error shown in the screen:
lblErrorText.setText("Error updating combo.");
Is there any way to return to presentation once first error is caught without overriding by next errors?
Maybe I misunderstood the concept but I want to catch all possible errors because:
-If connection is OK but method in 2nd layer fails it should throw ERROR_SELECTING_PRIMARY_KEY.
-If 2nd layer (calculations) does it OK but there is error in presentation it should lead to ERROR_UPDATING_COMBO_BOX.
You can use e.getCause() which will return a Throwable and check if this cause belongs to MyException. In case it is, you can check the e.getCause() again recursively until you obtain the deepest error code in the stacktrace and perform the validation for this exception.
Here's an example:
public MyException getDeepestException(MyException e) {
Throwable t = e.getCause();
if (t instanceof MyException) {
return getDeepestException((MyException)t);
}
return e;
}
As pointed out by #RealSkeptic, in order to use this approach, you will need to add an additional constructor to your custom exception:
public MyException(String message, Throwable cause, String errorCode){
super(message, cause);
this.errorCode = errorCode;
}
And when throwing your exception, call the proper constructor:
try {
//...
} catch (SomeException e) {
throw new MyException(<a proper message should be here>, e, "ERROR_SELECTING_PRIMARY_KEY");
}
If I understand you correctly, if the exception caught by one package happens to be a MyException, you want the original MyException to be passed up, otherwise (if the exception is some other type of Exception) you want to create a new MyException.
In this case, you should have two catch clauses.
try {
// Whatever you do in the try clause
} catch ( MyException myEx ) {
throw myEx;
} catch ( Exception e ) {
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
}