如何在 Spock 測試中檢查記錄的訊息
一、簡介
當我們的程式碼執行時,我們經常記錄感興趣的事件。其中一些事件非常重要,我們希望確保記錄我們的消息。
在本教程中,我們將學習如何驗證我們的類別是否在 Spock 測試中記錄了特定訊息。我們將使用 Spring 的預設日誌框架 Logback 中的ListAppender
來捕獲訊息以供以後檢查。
2. 設定
首先,讓我們建立一個ClassWithLogger
Java 類,用於記錄我們想要驗證的一些資訊和警告訊息。讓我們使用Slf4j
註釋來實例化記錄器,並添加一個在資訊層級記錄訊息的方法:
@Slf4j
public class ClassWithLogger {
void logInfo() {
log.info("info message");
}
}
3.我們的測試框架
現在讓我們建立一個ClassWithLoggerTest
Specification
,並以ClassWithLogger
實例作為主題:
class ClassWithLoggerTest extends Specification {
@Subject
def subject = new ClassWithLogger()
}
接下來,我們必須設定一個Logger
來監聽ClassWithLogger
訊息。因此,讓我們從LoggerFactory
取得一個Logger
並將其轉換為 Logback Logger
實例以使用 Logback 的功能。
def logger = (Logger) LoggerFactory.getLogger(ClassWithLogger)
之後,**讓我們建立一個ListAppender
來收集訊息並將附加程式新增到我們的Logger.
**讓我們使用一種setup
方法,以便為每個測試重置我們收集的訊息:
def setup() {
listAppender = new ListAppender<>()
listAppender.start()
logger.addAppender(listAppender)
}
設定好ListAppender
後,我們就可以監聽日誌訊息、收集它們並在測試中驗證它們。
4. 檢查簡單訊息
讓我們編寫第一個測試來記錄訊息並檢查它。因此,讓我們透過呼叫ClassWithLogger
的logInfo
方法來記錄INFO
訊息,並驗證它是否在ListAppender
的訊息List
中,並且具有預期的文字和日誌等級:
def "when our subject logs an info message then we validate an info message was logged"() {
when: "we invoke a method that logs an info message"
subject.logInfo()
then: "we get our expected message"
with(listAppender.list[0]) {
getMessage() == expectedText
getLevel() == Level.INFO
}
}
在這種情況下,我們知道我們的訊息是記錄的第一個也是唯一一條訊息,因此我們可以安全地在ListAppender
捕獲的訊息清單中的索引 0 處檢查它。
當我們正在尋找的日誌事件不一定是第一個訊息時,我們將需要更強大的方法。在這種情況下,讓我們串流傳輸訊息列表並過濾它以查找我們的訊息:
then: "we get our expected message"
def ourMessage = listAppender.list.stream()
.filter(logEvent -> logEvent.getMessage().contains(expectedText))
.findAny()
ourMessage.isPresent()
and: "the details match"
with(ourMessage.get()) {
getMessage() == expectedText
getLevel() == Level.INFO
}
5. 檢查格式化訊息
當我們對LoggingEvent
呼叫getMessage
時,它會傳回模板而不是格式化字串。對於簡單訊息,這就是我們所需要的,但是當我們在日誌訊息中新增參數時,我們必須使用getFormattedMessage
來檢查實際記錄的訊息。
因此,讓我們在ClassWithLogger
加入一個logInfoWithParameter
方法,該方法使用範本String
和參數來記錄訊息:
void logInfoWithParameter(String extraData) {
log.info("info message: {}", extraData);
}
現在,讓我們寫一個測試來呼叫我們的新方法:
def "when our subject logs an info message from a template then we validate the an info message was logged with a parameter"() {
when: "we invoke a method that logs info messages"
subject.logInfoWithParameter("parameter")
}
最後,讓我們檢查第一筆記錄的訊息,以確保LoggingEvent
的getArgumentArray
中的第一個與我們的參數值匹配,並使用getFormattedMessage
驗證完整的訊息:
then: 'the details match for the first message in the list'
with (listAppender.list[0]) {
getMessage() == 'info message: {}'
getArgumentArray()[0] == 'parameter'
getFormattedMessage() == 'info message: parameter'
getLevel() == Level.INFO
}
請注意, getMessage
傳回模板String
而getFormattedMessage
傳回實際記錄的訊息。
六、總結
在本文中,我們學習如何使用 Logback 的ListAppender
來收集日誌訊息並使用LoggingEvent
來檢查簡單的訊息。我們也學習如何驗證使用帶有參數的範本化字串以及參數值本身記錄的訊息。
與往常一樣,本教學的源代碼位於 GitHub 上。