Core Java

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 inject Logger via Dependency Injection.
  • via Mockito.mock(LoggerFactoryBean.class) if services inject LoggerFactoryBean.
  • via MockedStatic<LoggerFactory> if services contain a static final Logger.

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 Logger bean a name in case there are more than one loggers in the same application.
  • Line 14: the Logger instance is created for DemoServiceWithLogger class. 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: LoggerFactoryBean can instantiate any Logger instance 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 the DemoServiceWithLogger constructor.

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 LoggerFactoryBean is injected by the DemoServiceWithLoggerFactory constructor.

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 logger is a static final field.

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 Logger instance is created by Mockito.mock(Logger.class).
  • Line 18: create the DemoServiceWithLogger instance 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 Logger and LoggerFactoryBean instances.
  • 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 LoggerFactory via mockStatic method.

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.

Download
You can download the full source code of this example here: Mocking Logger and LoggerFactory Example

Mary Zheng

Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button