1

How to test the below java catch block where in catch() doesnt throw exception back.

class ErrorTransImpl {
  private static final Logger logger = Logger.getLogger(ErrorTransImpl.class);

  public int errorCatcher(ErrorTrans transError){
    int ct = 0;
    if (transError != null){
      String query = "INSERT INTO tab_1 (rw1,rw2,rw3,rw4,rw5) VALUES (?,?,?,?,?)";
      try {
        ct =  jdbcTemplate.update(query, new Object[] {transError.col1(),transError.col2(), transError.col3(),transError.col4(),transError.col5()});
      }catch (DataAccessException ex) {
        logger.error(ex);
      }
    }
    return ct;
  }
}

I tried testing as below, but: 1>Unable to get into catch block. 2> Unable to test catch() even if inside as it doesnt throw exception back.

def 'throw DataAccess Exception upon incorrect update'() {
  given:
  def log = Mock(Logger)
  def originalLogger = ErrorTransImpl.logger
  ErrorTransImpl.logger = log
  ErrorTransImpl errTransImpl = Spy() {
    jdbcTemplate >> {
      throw new DataAccessException() {
        @Override
        String getMessage() {
          return super.getMessage()
        }
      }
    }
  }

  when:
  errTransImpl.errorCatcher(new ErrorTrans())

  then:
  //            thrown DataAccessException
  //Not sure what to assert or test here ??
}    

Can anyone help on how i test this?

kriegaex
  • 63,017
  • 15
  • 111
  • 202
PravMan
  • 21
  • 4
  • Does normal mocking, i.e., 1 * log.error(*_) not work? – Leonard Brünings Sep 22 '22 at 19:50
  • Please learn what an [MCVE](https://stackoverflow.com/help/mcve) is and edit your question accordingly. Thank you so much. Please also do not post longer code snippets in comments like you did before. They are unreadable. Instead, edit the question and notify others via a short comment. At least, plese let me know which logging framework in which version you are using. Some of your classes and method calls suggest Logback, others look more like Log4J. Otherwise, the best I can do is write a speculative answer, which might not be very helpful. – kriegaex Sep 24 '22 at 09:43
  • Besides, what stops you from removing the `final` specifier from the logger declaration, other than convention? Then it would be easily mockable without the need to define a mock appender. Without add-ons to Spock or manual use of reflection, you cannot assign a mock to the logger field. This is the main reason why you need the suggested appender in the first place. – kriegaex Sep 24 '22 at 09:45
  • I decided to close the question as a duplicate. Just follow the link to the other question above to see a full example of a class logging with SLF4J and a data-driven Spock spec verifying various logging scenarios and log channels, utilising a mocked Logback appender. There is also a link to the code in GWC (Groovy Web Console), i.e. you can easily run the example right in your web browser. If you have any further questions, feel free to comment here. – kriegaex Sep 25 '22 at 07:19

1 Answers1

1

You need to test the behaviour that

ct =  jdbcTemplate.update(query, new Object[] {transError.col1(),transError.col2(), transError.col3(),transError.col4(),transError.col5()});

failed. Or, I don't really like this myself, you can check that the logger.error() was called.

Jocke
  • 2,189
  • 1
  • 16
  • 24
  • How do i check that the logger.error() was called ? Can you see what changes needed for test case above ? – PravMan Sep 22 '22 at 18:50
  • You'd have mock the logging configuration and install an appender which would let you retrieve the expected messages. https://stackoverflow.com/questions/38861416/junit-testing-log-statements – Queeg Sep 22 '22 at 19:24
  • @Hiran I tried based on the link as below but still getting error, what am i missing? def 'throw DataAccess Exception upon incorrect update_1'(){ setup: final Appender appender = Mockito.mock(Appender.class) final Logger logger = (Logger) LoggerFactory.getLogger(ErrorTransImpl.class) logger.addAppender(appender) appender.start() ErrorTransImpl errTransImpl = new ErrorTransImpl() errTransImpl.setJdbcTemplate(new JdbcTemplate(db.getDataSource())) when: errTransImpl.errorCatcher(new ErrorTrans()) then: assert "doing test" == appender.getEvents().get(0).getMessage(); } – PravMan Sep 22 '22 at 22:10