java - unitaria - ¿Cómo interceptar el registro SLF4J a través de una prueba JUnit?
pruebas unitarias (3)
Puede crear un appender personalizado
public class TestAppender extends AppenderBase<LoggingEvent> {
static List<LoggingEvent> events = new ArrayList<>();
@Override
protected void append(LoggingEvent e) {
events.add(e);
}
}
y configure logback-test.xml para usarlo. Ahora podemos verificar los eventos de registro de nuestra prueba:
@Test
public void test() {
...
Assert.assertEquals(1, TestAppender.events.size());
...
}
¿Es posible de alguna manera interceptar el registro (SLF4J + logback) y obtener un InputStream
(u otra cosa que sea legible) a través de un caso de prueba JUnit ...?
Puede usar slf4j-test desde http://projects.lidalia.org.uk/slf4j-test/ . Reemplaza toda la implementación logback slf4j por su propia implementación slf4j api para pruebas y proporciona una API para afirmar contra eventos de registro.
ejemplo:
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExcludes>ch.qos.logback:logback-classic</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>
public class Slf4jUser {
private static final Logger logger = LoggerFactory.getLogger(Slf4jUser.class);
public void aMethodThatLogs() {
logger.info("Hello World!");
}
}
public class Slf4jUserTest {
Slf4jUser slf4jUser = new Slf4jUser();
TestLogger logger = TestLoggerFactory.getTestLogger(Slf4jUser.class);
@Test
public void aMethodThatLogsLogsAsExpected() {
slf4jUser.aMethodThatLogs();
assertThat(logger.getLoggingEvents(), is(asList(info("Hello World!"))));
}
@After
public void clearLoggers() {
TestLoggerFactory.clear();
}
}
Tuve problemas al probar registros de línea como: LOGGER.error (mensaje, excepción) .
La solución descrita en http://projects.lidalia.org.uk/slf4j-test/ intenta afirmar también en la excepción y no es fácil (y en mi opinión no tiene ningún valor) para recrear la stacktrace.
Lo resolví de esta manera:
import org.junit.Test;
import org.slf4j.Logger;
import uk.org.lidalia.slf4jext.LoggerFactory;
import uk.org.lidalia.slf4jtest.TestLogger;
import uk.org.lidalia.slf4jtest.TestLoggerFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static uk.org.lidalia.slf4jext.Level.ERROR;
import static uk.org.lidalia.slf4jext.Level.INFO;
public class Slf4jLoggerTest {
private static final Logger LOGGER = LoggerFactory.getLogger(Slf4jLoggerTest.class);
private void methodUnderTestInSomeClassInProductionCode() {
LOGGER.info("info message");
LOGGER.error("error message");
LOGGER.error("error message with exception", new RuntimeException("this part is not tested"));
}
private static final TestLogger TEST_LOGGER = TestLoggerFactory.getTestLogger(Slf4jLoggerTest.class);
@Test
public void testForMethod() throws Exception {
// when
methodUnderTestInSomeClassInProductionCode();
// then
assertThat(TEST_LOGGER.getLoggingEvents()).extracting("level", "message").contains(
tuple(INFO, "info message"),
tuple(ERROR, "error message"),
tuple(ERROR, "error message with exception")
);
}
}
Esto también tiene la ventaja de no tener que depender de la biblioteca Hamcrest Matchers .