Aktivieren von Protokollnachrichten mit JUnit

1. Einleitung

In diesem Tutorial sehen wir uns an, wie wir generierte Protokolle in JUnit-Tests behandeln können .

Wir werden die slf4j-api und die Logback- Implementierung verwenden und einen benutzerdefinierten Appender erstellen , den wir für die Protokollbestätigung verwenden können .

2. Maven-Abhängigkeiten

Bevor wir beginnen, fügen wir die Logback- Abhängigkeit hinzu. Da es die slf4j-api nativ implementiert , wird es automatisch heruntergeladen und von Maven Transitivity in das Projekt eingefügt:

 ch.qos.logback logback-classic. 1.2.3 

AssertJ bietet beim Testen sehr nützliche Funktionen. Fügen wir also auch seine Abhängigkeit zum Projekt hinzu:

 org.assertj assertj-core 3.15.0 test 

3. Eine grundlegende Geschäftsfunktion

Jetzt erstellen wir ein Objekt, das Protokolle generiert, auf denen unsere Tests basieren können.

Unser BusinessWorker- Objekt macht nur eine Methode verfügbar. Diese Methode generiert für jede Protokollebene ein Protokoll mit demselben Inhalt. Obwohl diese Methode in der realen Welt nicht so nützlich ist, eignet sie sich gut für unsere Testzwecke:

public class BusinessWorker { private static Logger LOGGER = LoggerFactory.getLogger(BusinessWorker.class); public void generateLogs(String msg) { LOGGER.trace(msg); LOGGER.debug(msg); LOGGER.info(msg); LOGGER.warn(msg); LOGGER.error(msg); } }

4. Testen der Protokolle

Wir möchten Protokolle generieren, also erstellen wir eine logback.xml- Datei im Ordner src / test / resources . Lassen Sie es uns so einfach wie möglich halten und alle Protokolle an einen CONSOLE-Appender umleiten :

     %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n       

4.1. MemoryAppender

Jetzt erstellen wir einen benutzerdefinierten Appender, der die Protokolle im Speicher hält . Wir werden den ListAppender , den Logback bietet , erweitern und ihn mit einigen nützlichen Methoden bereichern:

public class MemoryAppender extends ListAppender { public void reset() { this.list.clear(); } public boolean contains(String string, Level level) { return this.list.stream() .anyMatch(event -> event.getMessage().toString().contains(string) && event.getLevel().equals(level)); } public int countEventsForLogger(String loggerName) { return (int) this.list.stream() .filter(event -> event.getLoggerName().contains(loggerName)) .count(); } public List search(String string) { return this.list.stream() .filter(event -> event.getMessage().toString().contains(string)) .collect(Collectors.toList()); } public List search(String string, Level level) { return this.list.stream() .filter(event -> event.getMessage().toString().contains(string) && event.getLevel().equals(level)) .collect(Collectors.toList()); } public int getSize() { return this.list.size(); } public List getLoggedEvents() { return Collections.unmodifiableList(this.list); } }

Die MemoryAppender- Klasse verarbeitet eine Liste , die vom Protokollierungssystem automatisch ausgefüllt wird.

Es werden verschiedene Methoden vorgestellt, um eine Vielzahl von Testzwecken abzudecken:

  • reset () - löscht die Liste
  • enthält (msg, level) - gibt nur dann true zurück , wenn die Liste ein ILoggingEvent enthält , das dem angegebenen Inhalt und Schweregrad entspricht
  • countEventForLoggers (loggerName) - Gibt die Anzahl der ILoggingEvent zurück, die vom benannten Logger generiert wurden
  • search (msg) - gibt eine Liste von ILoggingEvent zurück , die dem spezifischen Inhalt entspricht
  • search (msg, level) - Gibt eine Liste von ILoggingEvent zurück , die dem angegebenen Inhalt und Schweregrad entspricht
  • getSize () - gibt die Anzahl der ILoggingEvent s zurück
  • getLoggedEvents () - gibt eine nicht veränderbare Ansicht der ILoggingEvent- Elemente zurück

4.2. Gerätetest

Als nächstes erstellen wir einen JUnit-Test für unseren Geschäftsmitarbeiter.

Wir deklarieren unseren MemoryAppender als Feld und fügen ihn programmgesteuert in das Protokollsystem ein. Dann starten wir den Appender.

Für unsere Tests setzen wir den Level auf DEBUG :

@Before public void setup() { Logger logger = (Logger) LoggerFactory.getLogger(LOGGER_NAME); memoryAppender = new MemoryAppender(); memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory()); logger.setLevel(Level.DEBUG); logger.addAppender(memoryAppender); memoryAppender.start(); }

Jetzt können wir einen einfachen Test erstellen, in dem wir unsere BusinessWorker- Klasse instanziieren und die generateLogs- Methode aufrufen . Wir können dann Aussagen zu den Protokollen machen, die es generiert:

@Test public void test() { BusinessWorker worker = new BusinessWorker(); worker.generateLogs(MSG); assertThat(memoryAppender.countEventsForLogger(LOGGER_NAME)).isEqualTo(4); assertThat(memoryAppender.search(MSG, Level.INFO).size()).isEqualTo(1); assertThat(memoryAppender.contains(MSG, Level.TRACE)).isFalse(); }

Dieser Test verwendet drei Funktionen des MemoryAppender :

  • Es wurden vier Protokolle erstellt - ein Eintrag pro Schweregrad sollte vorhanden sein, wobei die Ablaufverfolgungsstufe gefiltert werden sollte
  • Nur ein Protokolleintrag mit der Inhaltsnachricht mit dem Schweregrad INFO
  • Es ist kein Protokolleintrag mit Inhaltsnachricht und Schweregrad TRACE vorhanden

Wenn wir vorhaben, beim Generieren vieler Protokolle dieselbe Instanz dieser Klasse in derselben Testklasse zu verwenden, steigt die Speichernutzung. Wir können die MemoryAppender.clear () -Methode vor jedem Test aufrufen , um Speicher freizugeben und OutOfMemoryException zu vermeiden .

In diesem Beispiel haben wir den Umfang der beibehaltenen Protokolle auf das Paket LOGGER_NAME reduziert , das wir als „ com.baeldung.junit.log “ definiert haben. Wir könnten möglicherweise alle Protokolle mit LoggerFactory.getLogger (Logger.ROOT_LOGGER_NAME) aufbewahren, sollten dies jedoch nach Möglichkeit vermeiden, da dies viel Speicherplatz beanspruchen kann .

5. Schlussfolgerung

In diesem Tutorial haben wir gezeigt, wie die Protokollgenerierung in unseren Komponententests behandelt wird .

Wie immer ist der Code auf GitHub zu finden.