### Question:
ExceptionConverter extends ClassicConverter { @Override public String convert(final ILoggingEvent loggingEvent) { return Optional.ofNullable(loggingEvent) .map(this::getExceptionData) .orElse(NO_MSG); }  @Override String convert(final ILoggingEvent loggingEvent); static final String TARGET_CLASSES_PROPERTY_NAME; }### Answer:
@Test public void extractsTheExceptionClassMethodAndCreatesAUniqueExceptionId() throws Exception { ExceptionConverter converter = newExceptionConverter(); assertThat(converter.convert(loggingEvent).trim(), endsWith("[exceptionClass=com.hotels.styx.infrastructure.logging.ExceptionConverterTest, exceptionMethod=<init>, exceptionID=10d7182c]")); }
@Test public void gracefullyHandlesExceptionInstancesWithoutStackTrace() throws Exception { ExceptionConverter converter = newExceptionConverter(); ILoggingEvent errorEvent = newErrorLoggingEvent(new NoStackException()); assertThat(converter.convert(errorEvent), endsWith("")); }
@Test public void prioritizeTargetClassStackTraceElementsOverTheRootOnes() throws Exception { ExceptionConverter converter = newExceptionConverter(); converter.getContext() .putProperty(TARGET_CLASSES_PROPERTY_NAME, "TargetClass"); ILoggingEvent loggingEvent = newErrorLoggingEvent(new TargetClass().blow()); assertThat(converter.convert(loggingEvent).trim(), endsWith("[exceptionClass=com.hotels.styx.infrastructure.logging.ExceptionConverterTest$TargetClass, exceptionMethod=blow, exceptionID=8b93d529]")); }
@Test public void errorsIfTargetClassPropertyIsEmpty() throws Exception { ContextBase contextBase = new ContextBase(); StatusManager statusManager = mock(StatusManager.class); contextBase.setStatusManager(statusManager); ExceptionConverter converter = newExceptionConverter(contextBase); converter.getContext() .putProperty(TARGET_CLASSES_PROPERTY_NAME, ""); ILoggingEvent loggingEvent = newErrorLoggingEvent(new TargetClass().blow()); converter.convert(loggingEvent); verify(statusManager).add(any(ErrorStatus.class)); }