Hey, hello there 👋 Welcome. I hope you will like this library
I have created this library with ❤️ and passion, mostly during evening and night hours. If you use my library and want to appreciate the work I have done, please consider to sponsor this project as a way to contribute back to the community. There are 3 options available to pick from: GitHub, Ko-fi and Open Collective
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>logcaptor</artifactId>
<version>2.12.6</version>
<scope>test</scope>
</dependency>
testImplementation 'io.github.hakky54:logcaptor:2.12.6'
libraryDependencies += "io.github.hakky54" % "logcaptor" % "2.12.6" % Test
<dependency org="io.github.hakky54" name="logcaptor" rev="2.12.6" />
LogCaptor is a library which will enable you to easily capture logging entries for unit and integration testing purposes.
Do you want to capture the console output? Please have a look at ConsoleCaptor.
See the unit test LogCaptorShould for all the scenario's or checkout this project Java Tutorials which contains more isolated examples of the individual logging frameworks
| LogCaptor | SLF4J | Log4J | Java | Kotlin | Scala | Android |
|---|---|---|---|---|---|---|
| 2.8.x | 2.x.x | 2.22.x | 8+ | 1.5+ | 2.11+ | 24+ |
| 2.7.x | 1.x.x | 2.21.x | 8+ | 1.5+ | 2.11+ | 24+ |
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class FooService {
private static final Logger LOGGER = LogManager.getLogger(FooService.class);
public void sayHello() {
LOGGER.info("Keyboard not responding. Press any key to continue...");
LOGGER.warn("Congratulations, you are pregnant!");
}
}
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;
public class FooServiceShould {
@Test
public void logInfoAndWarnMessages() {
LogCaptor logCaptor = LogCaptor.forClass(FooService.class);
FooService fooService = new FooService();
fooService.sayHello();
// Get logs based on level
assertThat(logCaptor.getInfoLogs()).containsExactly("Keyboard not responding. Press any key to continue...");
assertThat(logCaptor.getWarnLogs()).containsExactly("Congratulations, you are pregnant!");
// Get all logs
assertThat(logCaptor.getLogs())
.hasSize(2)
.contains(
"Keyboard not responding. Press any key to continue...",
"Congratulations, you are pregnant!"
);
}
}
import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
public class FooServiceShould {
private static LogCaptor logCaptor;
private static final String EXPECTED_INFO_MESSAGE = "Keyboard not responding. Press any key to continue...";
private static final String EXPECTED_WARN_MESSAGE = "Congratulations, you are pregnant!";
@BeforeAll
public static void setupLogCaptor() {
logCaptor = LogCaptor.forClass(FooService.class);
}
@AfterEach
public void clearLogs() {
logCaptor.clearLogs();
}
@AfterAll
public static void tearDown() {
logCaptor.close();
}
@Test
public void logInfoAndWarnMessagesAndGetWithEnum() {
FooService service = new FooService();
service.sayHello();
assertThat(logCaptor.getInfoLogs()).containsExactly(EXPECTED_INFO_MESSAGE);
assertThat(logCaptor.getWarnLogs()).containsExactly(EXPECTED_WARN_MESSAGE);
assertThat(logCaptor.getLogs()).hasSize(2);
}
@Test
public void logInfoAndWarnMessagesAndGetWithString() {
FooService service = new FooService();
service.sayHello();
assertThat(logCaptor.getInfoLogs()).containsExactly(EXPECTED_INFO_MESSAGE);
assertThat(logCaptor.getWarnLogs()).containsExactly(EXPECTED_WARN_MESSAGE);
assertThat(logCaptor.getLogs()).hasSize(2);
}
}
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class FooService {
private static final Logger LOGGER = LogManager.getLogger(FooService.class);
public void sayHello() {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Keyboard not responding. Press any key to continue...");
}
LOGGER.info("Congratulations, you are pregnant!");
}
}
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;
public class FooServiceShould {
@Test
public void logInfoAndWarnMessages() {
LogCaptor logCaptor = LogCaptor.forClass(FooService.class);
logCaptor.setLogLevelToInfo();
FooService fooService = new FooService();
fooService.sayHello();
assertThat(logCaptor.getInfoLogs()).contains("Congratulations, you are pregnant!");
assertThat(logCaptor.getDebugLogs())
.doesNotContain("Keyboard not responding. Press any key to continue...")
.isEmpty();
}
}
import nl.altindag.log.service.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class FooService {
private static final Logger LOGGER = LoggerFactory.getLogger(ZooService.class);
@Override
public void sayHello() {
try {
tryToSpeak();
} catch (IOException e) {
LOGGER.error("Caught unexpected exception", e);
}
}
private void tryToSpeak() throws IOException {
throw new IOException("KABOOM!");
}
}
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import nl.altindag.log.model.LogEvent;
import org.junit.jupiter.api.Test;
public class FooServiceShould {
@Test
void captureLoggingEventsContainingException() {
LogCaptor logCaptor = LogCaptor.forClass(ZooService.class);
FooService service = new FooService();
service.sayHello();
List<LogEvent> logEvents = logCaptor.getLogEvents();
assertThat(logEvents).hasSize(1);
LogEvent logEvent = logEvents.get(0);
assertThat(logEvent.getMessage()).isEqualTo("Caught unexpected exception");
assertThat(logEvent.getLevel()).isEqualTo("ERROR");
assertThat(logEvent.getThrowable()).isPresent();
assertThat(logEvent.getThrowable().get())
.hasMessage("KABOOM!")
.isInstanceOf(IOException.class);
}
}
import nl.altindag.log.service.LogMessage;
import nl.altindag.log.service.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class FooService {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceWithSlf4jAndMdcHeaders.class);
public void sayHello() {
try {
MDC.put("my-mdc-key", "my-mdc-value");
LOGGER.info(LogMessage.INFO.getMessage());
} finally {
MDC.clear();
}
LOGGER.info("Hello there!");
}
}
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import nl.altindag.log.model.LogEvent;
import org.junit.jupiter.api.Test;
public class FooServiceShould {
@Test
void captureLoggingEventsContainingMdc() {
LogCaptor logCaptor = LogCaptor.forClass(FooService.class);
FooService service = new FooService();
service.sayHello();
List<LogEvent> logEvents = logCaptor.getLogEvents();
assertThat(logEvents).hasSize(2);
assertThat(logEvents.get(0).getDiagnosticContext())
.hasSize(1)
.extractingByKey("my-mdc-key")
.isEqualTo("my-mdc-value");
assertThat(logEvents.get(1).getDiagnosticContext()).isEmpty();
}
}
In some use cases a unit test can generate too many logs by another class. Thi
$ claude mcp add log-captor \
-- python -m otcore.mcp_server <graph>