Logboekberichten vastleggen met JUnit

1. Inleiding

In deze tutorial zullen we kijken hoe we kunnen gegenereerde logboeken in JUnit-testen behandelen.

We gebruiken de slf4j-api en de inloggenimplementatie en creëer een aangepaste appender die we kunnen gebruiken voor logboekbevestiging.

2. Maven afhankelijkheden

Voordat we beginnen, voegen we het inloggen afhankelijkheid. Omdat het native de slf4j-api, wordt het automatisch gedownload en in het project geïnjecteerd door Maven transitivity:

 ch.qos.logback logback-classic. 1.2.3 

Beweren J. biedt zeer nuttige functies bij het testen, dus laten we de afhankelijkheid ervan ook aan het project toevoegen:

 org.assertj assertj-core 3.15.0 test 

3. Een basisbedrijfsfunctie

Laten we nu een object maken dat logboeken genereert waarop we onze tests kunnen baseren.

Onze BusinessWorker object zal slechts één methode weergeven. Deze methode genereert een logboek met dezelfde inhoud voor elk logboekniveau. Hoewel deze methode in de echte wereld niet zo handig is, zal hij goed van pas komen voor onze testdoeleinden:

openbare klasse BusinessWorker {privé statische Logger LOGGER = LoggerFactory.getLogger (BusinessWorker.class); public void generationLogs (String msg) {LOGGER.trace (msg); LOGGER.debug (msg); LOGGER.info (msg); LOGGER.waarschuwing (msg); LOGGER.fout (msg); }}

4. Testen van de logboeken

We willen logboeken genereren, dus laten we een logback.xml bestand in het src / test / resources map. Laten we het zo simpel mogelijk houden en alle logboeken omleiden naar een TROOSTEN appender:

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

4.1. MemoryAppender

Laten we nu een aangepaste appender die logboeken in het geheugen bijhoudt. Goed verleng de ListAppender dat inloggen aanbiedingen, en we zullen het verrijken met een paar handige methoden:

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

De MemoryAppender klasse behandelt een Lijst dat automatisch wordt ingevuld door het logboeksysteem.

Het legt een verscheidenheid aan methoden bloot om een ​​breed scala aan testdoeleinden te dekken:

  • resetten () - wist de lijst
  • bevat (msg, niveau) - geeft terug waar alleen als de lijst een ILoggingEvent overeenkomend met de opgegeven inhoud en het ernstniveau
  • countEventForLoggers (loggerName) - geeft het aantal terug ILoggingEvent gegenereerd door benoemde logger
  • zoeken (msg) - geeft een Lijst van ILoggingEvent passend bij de specifieke inhoud
  • zoeken (msg, niveau) - geeft een Lijst van ILoggingEvent overeenkomend met de opgegeven inhoud en het ernstniveau
  • getSize () - geeft het aantal terug ILoggingEvents
  • getLoggedEvents () - geeft een niet-wijzigbare weergave van de ILoggingEvent elementen

4.2. Hoofdstuk toets

Laten we vervolgens een JUnit-test maken voor onze zakelijke medewerker.

We verklaren onze MemoryAppender als een veld en injecteer het programmatisch in het logboeksysteem. Vervolgens starten we de appender.

Voor onze tests stellen we het niveau in op DEBUG:

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

Nu kunnen we een eenvoudige test maken waarin we onze instantiëren BusinessWorker class en bel de GenereerLogs methode. We kunnen dan beweringen doen over de logboeken die het genereert:

@Test openbare ongeldige test () {BusinessWorker-werknemer = nieuwe 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 (); }

Deze test maakt gebruik van drie functies van de MemoryAppender:

  • Er zijn vier logboeken gegenereerd - er moet één vermelding per ernst aanwezig zijn, met het traceringsniveau gefilterd
  • Slechts één logboekinvoer met de inhoud bericht met de ernst van INFO
  • Er is geen logboekinvoer aanwezig met inhoud bericht en ernst SPOOR

Als we van plan zijn om dezelfde instantie van deze klasse binnen dezelfde testklasse te gebruiken bij het genereren van veel logboeken, zal het geheugengebruik toenemen. We kunnen een beroep doen op de MemoryAppender.clear () methode voor elke test om geheugen vrij te maken en te vermijden OutOfMemoryException.

In dit voorbeeld hebben we het bereik van de bewaarde logboeken teruggebracht tot het LOGGER_NAME pakket, dat we hebben gedefinieerd als "com.baeldung.junit.log“. We kunnen mogelijk alle logboeken bewaren met LoggerFactory.getLogger (Logger.ROOT_LOGGER_NAME), maar we moeten dit waar mogelijk vermijden, omdat het veel geheugen kan vergen.

5. Conclusie

Met deze tutorial hebben we het gedemonstreerd hoe loggen in onze unit tests te dekken.

Zoals altijd is de code te vinden op GitHub.