I'm trying to write a unit test to test this piece of code, but I falled in Mockito/Powermockito limits with native class java.lang.Class as explained here.
How could I test this:
Method[] serverStatusMethods = serverStatus.getClass().getMethods();
for (Method serverStatusMethod : serverStatusMethods) {
if (serverStatusMethod.getName().equalsIgnoreCase("get" + field)) {
serverStatusMethod.setAccessible(true);
try {
Number value = (Number) serverStatusMethod.invoke(serverStatus);
response = new DataResponse(field + " value", value);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(StatusServlet.class.getName()).log(Level.SEVERE, null, ex);
response = new ErrorResponse(HttpStatus.Code.INTERNAL_SERVER_ERROR, ex);
}
break;
}
}
to throw this exceptions intentionally in test case:
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(StatusServlet.class.getName()).log(Level.SEVERE, null, ex);
response = new ErrorResponse(HttpStatus.Code.INTERNAL_SERVER_ERROR, ex);
}
Do what you do whenever mocking a class is too difficult: add another layer of abstraction. E.g. extract the reflective operations into a separate method:
public Number resolveServerStatus(Object serverStatus)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Method[] serverStatusMethods = serverStatus.getClass().getMethods();
for (Method serverStatusMethod : serverStatusMethods) {
if (serverStatusMethod.getName().equalsIgnoreCase("get" + field)) {
serverStatusMethod.setAccessible(true);
return (Number) serverStatusMethod.invoke(serverStatus);
}
}
}
Now mock the resolveServerStatus
method.
This is what you should have done in the first place if you had followed the single responsibility principle. Your method had two responsibilities: resolving the status number and converting it to DataResponse
object. The multiple responsibilities made testing the method dififficult.