Menegaskan Pesan Log Dengan JUnit

1. Perkenalan

Dalam tutorial ini, kita akan melihat bagaimana kita dapat menutupi log yang dihasilkan dalam pengujian JUnit .

Kita akan menggunakan slf4j-api dan implementasi logback serta membuat appender khusus yang bisa kita gunakan untuk pernyataan log .

2. Ketergantungan Maven

Sebelum kita mulai, mari tambahkan dependensi logback . Karena secara native mengimplementasikan slf4j-api , secara otomatis didownload dan dimasukkan ke dalam proyek oleh transitivitas Maven:

 ch.qos.logback logback-classic. 1.2.3 

AssertJ menawarkan fungsi yang sangat berguna saat menguji, jadi mari tambahkan ketergantungannya ke proyek juga:

 org.assertj assertj-core 3.15.0 test 

3. Fungsi Bisnis Dasar

Sekarang, mari buat sebuah objek yang akan menghasilkan log yang dapat menjadi dasar pengujian kita.

Objek BusinessWorker kami hanya akan menampilkan satu metode. Metode ini akan menghasilkan log dengan konten yang sama untuk setiap tingkat log. Meskipun metode ini tidak terlalu berguna di dunia nyata, ini akan berfungsi dengan baik untuk tujuan pengujian kami:

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. Menguji Log

Kami ingin membuat log, jadi mari buat file logback.xml di folder src / test / resources . Mari buat sesederhana mungkin dan alihkan semua log ke appender CONSOLE :

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

4.1. MemoryAppender

Sekarang, mari buat appender khusus yang menyimpan log di memori . Kami akan memperluas ListAppender yang ditawarkan oleh logback , dan kami akan memperkayanya dengan beberapa metode yang berguna:

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); } }

Kelas MemoryAppender menangani Daftar yang secara otomatis diisi oleh sistem logging.

Ini memperlihatkan berbagai metode untuk mencakup berbagai tujuan pengujian:

  • reset () - menghapus daftar
  • berisi (msg, level) - mengembalikan true hanya jika daftar berisi ILoggingEvent yang cocok dengan konten dan tingkat keparahan yang ditentukan
  • countEventForLoggers (loggerName) - mengembalikan jumlah ILoggingEvent yang dibuat oleh logger bernama
  • mencari (msg) - mengembalikan Daftar dari ILoggingEvent cocok dengan konten yang spesifik
  • mencari (msg, tingkat) - mengembalikan sebuah Daftar dari ILoggingEvent cocok dengan konten tertentu dan tingkat keparahan
  • getSize () - mengembalikan jumlah ILoggingEvent s
  • getLoggedEvents () - mengembalikan tampilan elemen ILoggingEvent yang tidak dapat dimodifikasi

4.2. Uji Unit

Selanjutnya, mari buat pengujian JUnit untuk pekerja bisnis kita.

Kami akan mendeklarasikan MemoryAppender kami sebagai bidang dan secara terprogram memasukkannya ke dalam sistem log. Kemudian, kita akan memulai appender.

Untuk pengujian kami, kami akan menyetel level ke 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(); }

Sekarang kita bisa membuat tes sederhana di mana kita memberi contoh kelas BusinessWorker kita dan memanggil metode generateLogs . Kami kemudian dapat membuat pernyataan pada log yang dihasilkannya:

@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(); }

Tes ini menggunakan tiga fitur MemoryAppender :

  • Empat log telah dibuat - satu entri per tingkat keparahan harus ada, dengan tingkat jejak difilter
  • Hanya satu entri log dengan pesan konten dengan tingkat keparahan INFO
  • Tidak ada entri log dengan pesan konten dan tingkat keparahan TRACE

Jika kita berencana untuk menggunakan instance yang sama dari kelas ini di dalam kelas pengujian yang sama saat membuat banyak log, penggunaan memori akan meningkat. Kita bisa memanggil metode MemoryAppender.clear () sebelum setiap pengujian untuk membebaskan memori dan menghindari OutOfMemoryException .

Dalam contoh ini, kami telah mengurangi cakupan log yang dipertahankan ke paket LOGGER_NAME , yang kami definisikan sebagai " com.baeldung.junit.log ". Kami berpotensi menyimpan semua log dengan LoggerFactory.getLogger (Logger.ROOT_LOGGER_NAME), tetapi kami harus menghindari ini jika memungkinkan karena dapat menghabiskan banyak memori .

5. Kesimpulan

Dengan tutorial ini, kami telah mendemonstrasikan cara mencakup pembuatan log dalam pengujian unit kami .

Seperti biasa, kode dapat ditemukan di GitHub.