Search code examples
javajpajunitspring-data-jpamockito

How to unit test JpaSystemException error handling logic?


I have a JpaRepository that is calling an Oracle function, which can return a handfull of application errors. I've successfully handled the errors with the following util method:

    private Integer pullOracleErrorCodeFromJpaException(JpaSystemException t) {
    if (t.getCause().getCause() instanceof SQLException) {
        SQLException sqlException = (SQLException) t.getCause().getCause();
        return sqlException.getErrorCode();
    }
    return null;
}

I can then key off of returned error in the JpaSystemException catch block like so:

try {
personProfile = personRepository.findPersonProfile(
        request.getPersonId(),
        request.getBillingAccount(),
        request.getCustomerAccount()
} catch (JpaSystemException jse) {

Integer oracleErrorCode = pullOracleErrorCodeFromJpaException(jse);

if (oracleErrorCode == null) {
    throw new OracleErrorException("Oracle Function returned an error.");
}
else if (oracleErrorCode == 20001) {
    throw new InvalidRequestException("At least one variable is required to run the acp usac function.");
} else if (oracleErrorCode == 20002) {
    throw new InvalidRequestException("Make sure you enter billing account in the billing account field.");
} else if (oracleErrorCode == 20003) {
    throw new InvalidRequestException("Make sure you enter a customer account in the customer account field.");
} else {
    throw new OracleErrorException("Oracle function returned an unrecognized application error.");
}

Which works great! However I'm having a hard time figuring out how to unit test the various return codes from Oracle, since they're 2 exceptions deep. Is it possible to set a cause 2 levels deep in a org.mockito.Mockito.doThrow so that I can validate each Oracle error code throws the correct subsequent exception?


Solution

  • JpaSystemException has a public constructor, so you can simply create an instance of it for your test:

    final int errorCode = 20001;
    final Exception ex = new JpaSystemException(
        new Exception(
            new SQLException("reason", "sqlstate", errorCode)));
    
    // ex.getCause().getCause() is your SQLException