Mocking Logger and LoggerFactory Example
1. Introduction
The SLF4J library provides the Logger interface and LoggerFactory utility class to create a logger instance for a given class. Application utilizes the logging message to troubleshoot problems. In this example, I will demonstrate three ways to mock Logger and LoggerFactory in a Spring Boot Web Project:
- via
Mockito.mock(Logger.class)if services injectLoggervia Dependency Injection. - via
Mockito.mock(LoggerFactoryBean.class)if services injectLoggerFactoryBean. - via
MockedStatic<LoggerFactory>if services contain astaticfinalLogger.
2. Setup
In this step, I will create a gradle project with Spring Web, mockito-core, and mockito-inline libraries via Spring Initializr.
2.1 Generated Build.gradle
The generated build.gradle file.
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.7'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'org.jcg.demo.zheng'
version = '0.0.1-SNAPSHOT'
description = 'Demo project for Spring Boot'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
configurations {
mockitoAgent
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// https://mvnrepository.com/artifact/org.mockito/mockito-core
testImplementation("org.mockito:mockito-core:5.20.0")
// https://mvnrepository.com/artifact/org.mockito/mockito-inline for static mocking
testImplementation("org.mockito:mockito-inline:5.2.0")
}
tasks.named('test') {
useJUnitPlatform()
}
2.2 Generated DemoApplication
The generated DemoApplication.java file.
DemoApplication.java
package org.jcg.demo.zheng.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2.3 Create LoggerConfiguration
In this step, I will create LoggerConfiguration.java to configure a Logger Spring Bean.
LoggerConfiguration.java
package org.jcg.demo.zheng.demo;
import org.jcg.demo.zheng.demo.service.DemoServiceWithLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoggerConfiguration {
@Bean(name = "demoServiceLogger")
public Logger demoServiceWithLogger() {
return LoggerFactory.getLogger(DemoServiceWithLogger.class);
}
}
- Line 12: give the
Loggerbean a name in case there are more than one loggers in the same application. - Line 14: the
Loggerinstance is created forDemoServiceWithLoggerclass. If there are more than 3 loggers need to be configured, then step 2.4 will be the better approach.
2.4 Create LoggerFactoryBean
In this step, I will create LoggerFactoryBean.java as a Spring component.
LoggerFactoryBean.java
package org.jcg.demo.zheng.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class LoggerFactoryBean {
public Logger getLogger(Class<?> clazz) {
return LoggerFactory.getLogger(clazz);
}
}
- Line 9, 10:
LoggerFactoryBeancan instantiate anyLoggerinstance for any class.
3. Java Service with Logger and LoggerFactory
3.1 Java Service with Injected final Logger
In this step, I will create a DemoServiceWithLogger.java that injects a Logger bean defined at step 2.3 from Spring Context.
DemoServiceWithLogger.java
package org.jcg.demo.zheng.demo.service;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceWithLogger {
private final Logger logger;
public DemoServiceWithLogger(@Qualifier("demoServiceLogger") Logger logger) {
this.logger = logger;
}
public void serviceWithLog(boolean isError) {
if (isError) {
logger.error("Ouch!");
} else {
logger.info("OK, not that bad.");
}
}
}
- Line 12: a spring bean with
name="demoServiceLogger"is injected by theDemoServiceWithLoggerconstructor.
3.2 Java Service with Injected final LoggerFactoryBean
In this step, I will create a DemoServiceWithLoggerFactory.java that injects a LoggerFactoryBean defined at step 2.4 from Spring Context.
DemoServiceWithLoggerFactory.java
package org.jcg.demo.zheng.demo.service;
import org.jcg.demo.zheng.demo.LoggerFactoryBean;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceWithLoggerFactory {
private final Logger logger;
public DemoServiceWithLoggerFactory(LoggerFactoryBean loggerFactory) {
this.logger = loggerFactory.getLogger(getClass());
}
public void serviceWithLog(boolean isError) {
if (isError) {
logger.error("Ouch!");
} else {
logger.info("OK, not that bad.");
}
}
}
- Line 12: a spring bean
LoggerFactoryBeanis injected by theDemoServiceWithLoggerFactoryconstructor.
3.3 Java Service with Static final Logger
In this step, I will create a DemoServiceWithStaticLogger.java that has a static final Logger.
DemoServiceWithStaticLogger.java
package org.jcg.demo.zheng.demo.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceWithStaticLogger {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceWithStaticLogger.class);
public void serviceWithLog(boolean isError) {
if (isError) {
logger.error("Ouch!");
} else {
logger.info("OK, not that bad.");
}
}
}
- Line 10: the
loggeris astatic finalfield.
4. Mock Logger and LoggerFactory
Mockito library provides mock() and mockStatic() methods. I will create three test classes to mock the Logger and LoggerFactory used in the services created in step 3.
4.1 Mock Logger
In this step, I will create a DemoServiceWithLoggerTest.java that mock the LoggerInterface with Mockito.mock(Logger.class).
DemoServiceWithLoggerTest.java
package org.jcg.demo.zheng.demo.service;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
class DemoServiceWithLoggerTest {
private DemoServiceWithLogger testClass;
private Logger mockLogger;
@BeforeEach
public void setup() {
mockLogger = Mockito.mock(Logger.class);
testClass = new DemoServiceWithLogger(mockLogger);
}
@Test
void test_error_log() {
testClass.serviceWithLog(true);
verify(mockLogger).error("Ouch!");
}
@Test
void test_info_log() {
testClass.serviceWithLog(false);
verify(mockLogger).info("OK, not that bad.");
}
}
- Line 17: the
Loggerinstance is created byMockito.mock(Logger.class). - Line 18: create the
DemoServiceWithLoggerinstance via constructor injection.
Run the JUnit test and capture the test output.
gradlew test –tests “org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerTest”
C:\MaryZheng\workspace\logdemo>gradlew test --tests "org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerTest" Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended BUILD SUCCESSFUL in 2s 4 actionable tasks: 1 executed, 3 up-to-date C:\MaryZheng\workspace\logdemo>
4.2 Mock Logger & LoggerFactory via LoggerFactoryBean
In this step, I will create a DemoServiceWithLoggerFactoryTest.java that mock the LoggerFactoryBean with Mockito.mock(Logger.class).
DemoServiceWithLoggerFactoryTest.java
package org.jcg.demo.zheng.demo.service;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.jcg.demo.zheng.demo.LoggerFactoryBean;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
class DemoServiceWithLoggerFactoryTest {
private DemoServiceWithLoggerFactory testClass;
private Logger mockLogger;
private LoggerFactoryBean mockLogFactory;
@BeforeEach
public void setup() {
mockLogger = Mockito.mock(Logger.class);
mockLogFactory = Mockito.mock(LoggerFactoryBean.class);
when(mockLogFactory.getLogger(DemoServiceWithLoggerFactory.class)).thenReturn(mockLogger);
testClass = new DemoServiceWithLoggerFactory(mockLogFactory);
}
@Test
void test_error_log() {
testClass.serviceWithLog(true);
verify(mockLogger).error("Ouch!");
}
@Test
void test_info_log() {
testClass.serviceWithLog(false);
verify(mockLogger).info("OK, not that bad.");
}
}
- Line 20, 21: Mock the
LoggerandLoggerFactoryBeaninstances. - Line 22: define the mock behavior.
Run the JUnit test and capture the test output.
gradlew test –tests “org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerFactoryTest”
C:\MaryZheng\workspace\logdemo>gradlew test --tests "org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerFactoryTest" Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended BUILD SUCCESSFUL in 2s 4 actionable tasks: 1 executed, 3 up-to-date C:\MaryZheng\workspace\logdemo>
4.3 Mock Logger & LoggerFactory via Mockito.mockStatic
In this step, I will create a DemoServiceWithStaticLoggerTest.java that mock the MockedStatic with Mockito.mockStatic(LoggerFactory.class).
DemoServiceWithStaticLoggerTest.java
package org.jcg.demo.zheng.demo.service;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class DemoServiceWithStaticLoggerTest {
@Test
public void test_log() {
Logger mockLogger = Mockito.mock(Logger.class);
try (MockedStatic<LoggerFactory> mockedFactory = Mockito.mockStatic(LoggerFactory.class)) {
mockedFactory.when(() -> LoggerFactory.getLogger(DemoServiceWithStaticLogger.class)).thenReturn(mockLogger);
DemoServiceWithStaticLogger testClass = new DemoServiceWithStaticLogger();
testClass.serviceWithLog(true);
verify(mockLogger).error("Ouch!");
testClass.serviceWithLog(false);
verify(mockLogger).info("OK, not that bad.");
}
}
}
- Mock the
LoggerFactoryviamockStaticmethod.
Run the JUnit test and capture the test output.
gradlew test –tests “org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerTest”
C:\MaryZheng\workspace\logdemo>gradlew test --tests "org.jcg.demo.zheng.demo.service.DemoServiceWithStaticLoggerTest" Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended BUILD SUCCESSFUL in 3s 5 actionable tasks: 3 executed, 2 up-to-date C:\MaryZheng\workspace\logdemo>
5. Demonstrate
5.1 Create DemoRestController
In this step, I will create a DemoRestController.java that includes the DemoServiceWithLogger, DemoServiceWithLoggerFactory, and DemoServiceWithStaticLogger.
DemoRestController.java
package org.jcg.demo.zheng.demo.rest;
import org.jcg.demo.zheng.demo.service.DemoServiceWithLogger;
import org.jcg.demo.zheng.demo.service.DemoServiceWithLoggerFactory;
import org.jcg.demo.zheng.demo.service.DemoServiceWithStaticLogger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo")
public class DemoRestController {
@Autowired
private DemoServiceWithLogger service1;
@Autowired
private DemoServiceWithLoggerFactory service2;
@Autowired
private DemoServiceWithStaticLogger service3;
@GetMapping("/logger")
public void demoLogger(@RequestParam("isError") boolean isError) {
service1.serviceWithLog(isError);
service2.serviceWithLog(isError);
service3.serviceWithLog(isError);
}
}
5.2 Demonstrate
In this step, I will start the DemoApplication and invoke http://localhost:8080/demo/logger?isError=false and http://localhost:8080/demo/logger?isError=true and capture the server log.
Server log
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.5.7) 2025-10-26T11:44:35.911-05:00 INFO 22360 --- [demo] [ main] o.jcg.demo.zheng.demo.DemoApplication : Starting DemoApplication using Java 21.0.8 with PID 22360 (C:\MaryZheng\workspace\logdemo\bin\main started by zzhen in C:\MaryZheng\workspace\logdemo) 2025-10-26T11:44:35.915-05:00 INFO 22360 --- [demo] [ main] o.jcg.demo.zheng.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default" 2025-10-26T11:44:36.855-05:00 INFO 22360 --- [demo] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2025-10-26T11:44:36.868-05:00 INFO 22360 --- [demo] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2025-10-26T11:44:36.868-05:00 INFO 22360 --- [demo] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.48] 2025-10-26T11:44:36.914-05:00 INFO 22360 --- [demo] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2025-10-26T11:44:36.916-05:00 INFO 22360 --- [demo] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 946 ms 2025-10-26T11:44:37.322-05:00 INFO 22360 --- [demo] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' 2025-10-26T11:44:37.332-05:00 INFO 22360 --- [demo] [ main] o.jcg.demo.zheng.demo.DemoApplication : Started DemoApplication in 1.851 seconds (process running for 2.251) 2025-10-26T11:44:44.856-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2025-10-26T11:44:44.856-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2025-10-26T11:44:44.857-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms 2025-10-26T11:44:44.887-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.j.d.z.d.service.DemoServiceWithLogger : OK, not that bad. 2025-10-26T11:44:44.887-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.j.d.z.d.s.DemoServiceWithLoggerFactory : OK, not that bad. 2025-10-26T11:44:52.029-05:00 INFO 22360 --- [demo] [nio-8080-exec-1] o.j.d.z.d.s.DemoServiceWithStaticLogger : OK, not that bad. 2025-10-26T11:45:05.800-05:00 ERROR 22360 --- [demo] [nio-8080-exec-2] o.j.d.z.d.service.DemoServiceWithLogger : Ouch! 2025-10-26T11:45:05.801-05:00 ERROR 22360 --- [demo] [nio-8080-exec-2] o.j.d.z.d.s.DemoServiceWithLoggerFactory : Ouch! 2025-10-26T11:45:13.222-05:00 ERROR 22360 --- [demo] [nio-8080-exec-2] o.j.d.z.d.s.DemoServiceWithStaticLogger : Ouch!
- Line 22-27: the logging messages match the unit test results.
6. Conclusion
In this example, I demonstrated three ways to mock the Logger and LoggerFactory using Mockito’s mockand mockStatic methods.
7. Download
This was an example of a gradle project which mocked Logger and LoggerFactory.
You can download the full source code of this example here: Mocking Logger and LoggerFactory Example

