package hu.advancedweb.scott.runtime; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import hu.advancedweb.scott.runtime.report.FailureRenderer; /** * An alternative way to produce the detailed failure reports is to register this JUnit listener. * * @see ScottReportingRule * @author David Csakvari */ public class ScottRunListener extends RunListener { private Description description; /** * Sometimes testFailure is called multiple times for a single test, * so we has to track the already augmented Exception objects. */ private Set<Object> augmentedExceptions = new HashSet<>(); @Override public void testStarted(Description description) throws Exception { this.description = description; augmentedExceptions.clear(); super.testStarted(description); } @Override public void testFailure(Failure failure) throws Exception { String scottReport = FailureRenderer.render(description, failure.getException()); setExceptionMessage(failure.getException(), scottReport); super.testFailure(failure); } private void setExceptionMessage(Object object, Object fieldValue) { if (!augmentedExceptions.contains(object)) { augmentedExceptions.add(object); final String fieldName = "detailMessage"; Class<?> clazz = object.getClass(); while (clazz != null) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, fieldValue); return; } catch (NoSuchFieldException e) { clazz = clazz.getSuperclass(); } catch (Exception e) { throw new IllegalStateException(e); } } } } }