Czy można w jakiś sposób przechwycić rejestrowanie (SLF4J + logback) i uzyskać InputStream
(lub coś innego, co można odczytać) za pomocą testu JUnit ...?Jak przechwycić logowanie SLF4J za pomocą testu JUnit?
Odpowiedz
Można tworzyć niestandardowe appender
public class TestAppender extends AppenderBase<LoggingEvent> {
static List<LoggingEvent> events = new ArrayList<>();
@Override
protected void append(LoggingEvent e) {
events.add(e);
}
}
i skonfigurować logback-test.xml go używać. Teraz możemy sprawdzić rejestrowania zdarzeń z naszego testu:
@Test
public void test() {
...
Assert.assertEquals(1, TestAppender.events.size());
...
}
Można użyć slf4j test z http://projects.lidalia.org.uk/slf4j-test/. Zastępuje implementację SLF4j całego logbacku poprzez własną implementację API slf4j dla testów i zapewnia api do potwierdzania zdarzeń rejestrowania.
przykład:
<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();
}
}
Dzięki za tę alternatywną odpowiedź! Wygląda bardzo użytecznie i prawdopodobnie wypróbuję to podejście również w przyszłości! Niestety, przyjąłem już drugą odpowiedź, która również jest poprawna. – carlspring
miałem problemy podczas testowania kłody linię, jak: LOGGER.error (komunikat wyjątku).
Rozwiązanie opisane w http://projects.lidalia.org.uk/slf4j-test/ próbuje również potwierdzić wyjątek i nie jest to łatwe (i moim zdaniem bezwartościowe) odtworzenie stosu stacków.
I rozwiązany w ten sposób:
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")
);
}
}
To także korzyść nie posiadające zależą Hamcrest dopasowujące bibliotekę.
Uwaga, jeśli używasz klasycznego logback + slf4j, musisz użyć 'ILoggingEvent' zamiast' LoggingEvent'. To właśnie dla mnie zadziałało. – etech
@Eggeniy Dorofeev Czy mógłbyś pokazać, jak skonfigurować logback-test.xml? – hipokito
Zakładam, że musisz wyczyścić 'zdarzenia' po każdym wykonaniu testu. –