Skip to content

Commit

Permalink
Added information about capturing static inner classes, fixed javadoc…
Browse files Browse the repository at this point in the history
… warnings
  • Loading branch information
Соболев Василий committed Jul 4, 2021
1 parent 932a754 commit 2cc594c
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ configurations {
}
```

## Capturing logs of static inner classes
LogCaptor successfully catches logs of static inner classes with `LogCaptor.forClass(StaticInnerClass.class)` construction
when SLF4J or JUL is used. This doesn't apply to Log4j2 because by default it uses `Class.getCanonicalName()`
inside instead of `Class.getName()`. You should use `LogCaptor.forName(StaticInnerClass.class.getCanonicalName())` for successful
test execution with Log4j2.

# Contributing

There are plenty of ways to contribute to this project:
Expand Down
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/nl/altindag/log/LogCaptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,28 @@ private LogCaptor(String loggerName) {

/**
* Captures all log messages
*
* @return LogCaptor instance for the root logger
*/
public static LogCaptor forRoot() {
return new LogCaptor(ROOT_LOGGER_NAME);
}

/**
* Captures log messages for the provided class
*
* @param clazz Class for capturing
* @return LogCaptor instance for the provided class
*/
public static <T> LogCaptor forClass(Class<T> clazz) {
public static LogCaptor forClass(Class<?> clazz) {
return new LogCaptor(clazz.getName());
}

/**
* Captures log messages for the provided logger name
*
* @param name Logger name for capturing
* @return LogCaptor instance for the provided logger name
*/
public static LogCaptor forName(String name) {
return new LogCaptor(name);
Expand Down
70 changes: 70 additions & 0 deletions src/test/java/nl/altindag/log/LogCaptorShould.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@
import nl.altindag.log.service.slfj4.ServiceWithSlf4j;
import nl.altindag.log.service.slfj4.ServiceWithSlf4jAndCustomException;
import nl.altindag.log.service.slfj4.ServiceWithSlf4jAndMdcHeaders;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.slf4j.Log4jLogger;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.MockedStatic;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -52,10 +56,12 @@
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
Expand Down Expand Up @@ -413,6 +419,70 @@ void detachAppenderWithAutoClosable() {
assertThat(fetchAppenders(logger)).isEmpty();
}

@ParameterizedTest(name = "[{index}] Capture no log events with Class.getCanonicalName()")
@MethodSource("fetchArgumentsForNoLogEvents")
void captureNoLogEventsFromStaticInnerClasses(Runnable staticInnerClassMethod) {
try (LogCaptor logCaptor = LogCaptor.forClass(StaticInnerTestClass.class)) {
staticInnerClassMethod.run();
assertThat(logCaptor.getLogEvents()).isEmpty();
}
}

@ParameterizedTest(name = "[{index}] Capture log events with Class.getName()")
@MethodSource("fetchArgumentsForLogEvents")
void captureLogEventsFromStaticInnerClasses(Runnable staticInnerClassMethod, String expectedMessage) {
try (LogCaptor logCaptor = LogCaptor.forClass(StaticInnerTestClass.class)) {
staticInnerClassMethod.run();

assertThat(logCaptor.getInfoLogs())
.hasSize(1)
.first()
.isEqualTo(expectedMessage);
}
}

private static class StaticInnerTestClass {
static void call(org.apache.logging.log4j.Logger logger) {
logger.info("Test message from Log4j2");
}

static void call(org.slf4j.Logger logger) {
logger.info("Test message from SLF4J");
}

static void call(java.util.logging.Logger logger) {
logger.info("Test message from JUL");
}
}

// MethodSource for captureNoLogEventsFromStaticInnerClasses
@SuppressWarnings("unused")
private static Stream<Arguments> fetchArgumentsForNoLogEvents() {
String canonicalName = StaticInnerTestClass.class.getCanonicalName();

Runnable log4j2 = () -> StaticInnerTestClass.call(LogManager.getLogger(StaticInnerTestClass.class));
Runnable slf4j = () -> StaticInnerTestClass.call(LoggerFactory.getLogger(canonicalName));
Runnable jul = () -> StaticInnerTestClass.call(java.util.logging.Logger.getLogger(canonicalName));

return Stream.of(arguments(log4j2), arguments(slf4j), arguments(jul));
}

// MethodSource for captureLogEventsFromStaticInnerClasses
@SuppressWarnings("unused")
private static Stream<Arguments> fetchArgumentsForLogEvents() {
String name = StaticInnerTestClass.class.getName();

Runnable log4j2 = () -> StaticInnerTestClass.call(LogManager.getLogger(name));
Runnable slf4j = () -> StaticInnerTestClass.call(LoggerFactory.getLogger(StaticInnerTestClass.class));
Runnable jul = () -> StaticInnerTestClass.call(java.util.logging.Logger.getLogger(name));

return Stream.of(
arguments(log4j2, "Test message from Log4j2"),
arguments(slf4j, "Test message from SLF4J"),
arguments(jul, "Test message from JUL")
);
}

private static void assertListAppender(Logger logger) {
assertThat(fetchAppenders(logger))
.hasSize(1)
Expand Down

0 comments on commit 2cc594c

Please sign in to comment.