How can I test logs of Spring Boot application?

Viewed 1569

I have an application that is a mix of Spring Boot, Jersey, and Camel applications. It starts as a Spring Boot app. I am writing integration tests, and I need to make asserts on logs?

For instance, I need to assert that the Camel route read a message from source A. How can I make reliable asserts on logs? Is there any industry standard for this?

NOTE: I tried finding any solution, but at the moment, I neither understand how to solve it nor can find ready solutions.

UPDATE 1: The detail that I underestimated, but it seems important. I use Kotlin, NOT Java. I tried applying answer, but it isn't one to one transferable to Kotlin.

UPDATE 2:

This is a conversion from Java to Kotlin. ListAppender doesn't have enough information to resolve the type in Kotlin.

class LoggerExtension : BeforeEachCallback, AfterEachCallback {
    private val listAppender: ListAppender<ILoggingEvent> = ListAppender<ILoggingEvent>()
    private val logger: Logger = LoggerFactory.getLogger(ROOT_LOGGER_NAME) as Logger

    override fun afterEach(extensionContext: ExtensionContext) {
        listAppender.stop()
        listAppender.list.clear()
        logger.detachAppender(listAppender)
    }

    override fun beforeEach(extensionContext: ExtensionContext) {
        logger.addAppender(listAppender)
        listAppender.start()
    }

    val messages: List<String>
        get() = listAppender.list.stream().map { e -> e.getMessage() }.collect(Collectors.toList())
    val formattedMessages: List<String>
        get() = listAppender.list.stream().map { e -> e.getFormattedMessage() }.collect(Collectors.toList())
}

Kotlin: Not enough information to infer type variable A

Not an error, but I have a feeling that it will fail in runtime:

private val logger: Logger = LoggerFactory.getLogger(ROOT_LOGGER_NAME) as Logger

1 Answers

Spring Boot comes with OutputCapture rule for JUnit 4 and OutputCaptureExtension for JUnit 5, that let you assert on text sent to standard output.

public class MyTest {

     @Rule
     public OutputCaptureRule output = new OutputCaptureRule();

     @Test
     public void test() {
         // test code
         assertThat(output).contains("ok");
     }

 }
Related