In continuing to this answer I wrote a unit test to verify that in case of error, the stack will be printed in the log file.
The tested method:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Logger logger = LoggerFactory.getLogger(getClass());
public long getFq(String fi) {
try {
return calcSomeThing(fi.toLowerCase());
} catch (Exception e) {
logger.error("unable to calculate SomeThing. Error: "
, e);
return -1;
}
}
The unit test:
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.slf4j.LoggerFactory;
@Test
public void getFileQualifier() {
// get Logback Logger
Logger logger = (Logger) LoggerFactory.getLogger(QService.class);
// create and start a ListAppender
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
listAppender.start();
// add the appender to the logger
// addAppender is outdated now
logger.addAppender(listAppender);
// call method under test
QService.getFq(null);
// JUnit assertions
List<ILoggingEvent> logsList = listAppender.list;
Assert.assertEquals("unable to calculate SomeThing. Error: ", logsList.get(0)
.getFormattedMessage());
Assert.assertEquals(Level.ERROR, logsList.get(0)
.getLevel());
Assert.assertEquals("java.lang.NullPointerException: null", logsList.get(1)
.getMessage());
Assert.assertEquals(Level.ERROR, logsList.get(1)
.getLevel());
Assert.assertThat("(QService.java", containsString(logsList.get(2)
.getMessage()));
Assert.assertEquals(Level.ERROR, logsList.get(2)
.getLevel());
}
Well, although I can see the stack is indeed printed in the log file, the unit test failed because of the
logsList
contains only one item (the first printed line only [unable to calculate SomeThing. Error: ]).
java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
Why does it happen and how it can be tested?
EDIT
Answers: the answers (all are quotes from @Gavin's answer and comment, thank you):
On the first question (Why does it happen) the answer is:
It looks to me that exceptions is stored separately from the message in the log event
On the second question (how it can be tested) the answer is:
to find what you are looking for in the list of log events and can be expressed in a manner suitable to your domain, e.g checking the that a Throwable was logged, perhaps looking in org.apache.log4j.spi.LoggingEvent for appropriate methods
Finally, my code to verify it was:
Assert.assertEquals(logsList.get(0).getThrowableProxy().getClassName(), "java.lang.NullPointerException");