I wrote a Util for slf4j Logger with generic log level with enable test.
In debug it looks good, but junit test failed for all parameter values
It’s very interresting why test failed, but also maiby it’s giving better way to generic log
with Slf4j…
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.event.Level;
import java.util.function.Consumer;
import java.util.function.Supplier;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class LogUtils {
public static void log(Logger log, Level level, Supplier<String> msg) {
getLogOperation(log, level).accept(msg);
}
private static Consumer<Supplier<String>> getLogOperation(Logger log, Level level) {
return switch (level) {
case TRACE -> (s -> {
if (log.isTraceEnabled()) {
log.trace(s.get());
}
});
case DEBUG -> (s -> {
if (log.isDebugEnabled()) {
log.debug(s.get());
}
});
case INFO -> (s -> {
if (log.isInfoEnabled()) {
log.info(s.get());
}
});
case WARN -> (s -> {
if (log.isWarnEnabled()) {
log.warn(s.get());
}
});
case ERROR -> s -> {
if (log.isErrorEnabled()) {
log.error(s.get());
}
};
};
}
}
My JUnit test is here
class LogUtilsTest {
@ParameterizedTest
@CsvSource({"TRACE", "DEBUG", "INFO", "WARN", "ERROR"})
void log(Level level) {
Logger logger = mock(Logger.class);
TestContainer container = mock(TestContainer.class);
LogUtils.log(logger, level, container::getId);
then(container).should(never()).getId();
enableLevel(logger, level);
LogUtils.log(logger, level, container::getId);
then(container).should().getId();
}
private static void enableLevel(Logger log, Level level) {
switch (level) {
case TRACE -> given(log.isTraceEnabled()).willReturn(true);
case DEBUG -> given(log.isTraceEnabled()).willReturn(true);
case INFO -> given(log.isTraceEnabled()).willReturn(true);
case WARN -> given(log.isTraceEnabled()).willReturn(true);
case ERROR -> given(log.isTraceEnabled()).willReturn(true);
}
}
static class TestContainer {
public String getId() {
return "id";
}
}
}
Test failed on Line:
then(container).should().getId(); : Wanted but not invoked Whatis wrong mit my test/code???
>Solution :
you are mocking wrong methods here (always it’s isTraceEnabled but should be different for different levels):
switch (level) {
case TRACE -> given(log.isTraceEnabled()).willReturn(true);
case DEBUG -> given(log.isTraceEnabled()).willReturn(true);
case INFO -> given(log.isTraceEnabled()).willReturn(true);
case WARN -> given(log.isTraceEnabled()).willReturn(true);
case ERROR -> given(log.isTraceEnabled()).willReturn(true);
}
}