Frighi
Frighi

Reputation: 466

Cannot unit test Java code uses reflection with Mockito nor PowerMockito

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);
}

Upvotes: 0

Views: 1058

Answers (1)

Torben
Torben

Reputation: 3911

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.

Upvotes: 2

Related Questions