Spring Boot中无需Mockito,为Void方法编写日志验证JUnit测试
没问题!针对你这个Spring Boot里的void方法日志验证需求,我给你准备了两种实用的测试方案,分别适合单元测试和集成测试场景,一起来看看:
方案一:单元测试(轻量快速,无需加载Spring上下文)
这种方案专注于测试业务逻辑本身,用SLF4J的测试日志捕获器配合Mockito模拟依赖,执行速度很快。
依赖准备(Maven示例)
Spring Boot的spring-boot-starter-test已经包含了所有需要的依赖,如果你是单独引入的话,可以添加这些:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-test</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency>
测试代码实现
假设你的业务类叫AdjustmentService,测试代码如下:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.test.TestLogger; import org.slf4j.test.TestLoggerFactory; import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class AdjustmentServiceTest { // 获取当前业务类的TestLogger,用来捕获日志输出 private final TestLogger testLogger = TestLoggerFactory.getTestLogger(AdjustmentService.class); // 注入测试目标类,Mockito会自动注入被mock的依赖 @InjectMocks private AdjustmentService adjustmentService; // Mock业务类依赖的组件(比如获取adjustmentList的Repository) @Mock private AdjustmentRepository adjustmentRepository; @Test void processAdjustmentFeed_WhenHasAdjustments_ShouldLogInfoMessage() { // 每次测试前清空日志,避免其他测试的日志干扰当前结果 testLogger.clear(); // 模拟依赖返回非空的调整列表 List<Adjustment> mockAdjustments = List.of(new Adjustment(), new Adjustment()); when(adjustmentRepository.getAdjustmentsAfter(any())).thenReturn(mockAdjustments); // 调用要测试的void方法 adjustmentService.processAdjustmentFeed(); // 验证INFO级别的日志里包含指定消息 assertThat(testLogger.getInfoEvents()) .anyMatch(event -> event.getMessage().contains("ADJUSTMENT FEED SIZE TO PUBLISH: 2")); } @Test void processAdjustmentFeed_WhenNoAdjustments_ShouldLogWarnMessage() { testLogger.clear(); // 模拟依赖返回空列表 when(adjustmentRepository.getAdjustmentsAfter(any())).thenReturn(Collections.emptyList()); adjustmentService.processAdjustmentFeed(); // 验证WARN级别的日志里包含指定消息 assertThat(testLogger.getWarnEvents()) .anyMatch(event -> event.getMessage().contains("NO ADJUSTMENT FEED FOUND TO PROCESS FROM")); } }
方案二:集成测试(加载完整Spring上下文)
如果需要验证整个Spring环境下的端到端行为(比如数据库交互、依赖注入是否正常),可以用Spring Boot提供的OutputCaptureExtension来捕获日志。
测试代码实现
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.beans.factory.annotation.Autowired; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @ExtendWith(OutputCaptureExtension.class) class AdjustmentServiceIntegrationTest { // 从Spring上下文自动注入业务类实例 @Autowired private AdjustmentService adjustmentService; @Test void processAdjustmentFeed_WhenHasAdjustments_ShouldLogInfoMessage(CapturedOutput output) { // 这里可以提前准备测试数据,比如往测试数据库插入两条调整记录 // ... adjustmentService.processAdjustmentFeed(); // 验证控制台输出的日志包含指定内容(INFO日志通常输出到标准输出) assertThat(output.getOut()).contains("ADJUSTMENT FEED SIZE TO PUBLISH: 2"); } @Test void processAdjustmentFeed_WhenNoAdjustments_ShouldLogWarnMessage(CapturedOutput output) { // 确保测试环境中没有待处理的调整记录 // ... adjustmentService.processAdjustmentFeed(); // WARN日志通常输出到标准错误流,所以用getErr()捕获 assertThat(output.getErr()).contains("NO ADJUSTMENT FEED FOUND TO PROCESS FROM"); } }
关键注意点
- 方案一适合快速验证业务逻辑,不需要启动Spring,测试执行速度快。
- 方案二适合验证完整流程,确保所有依赖组件协同工作正常。
- 每次测试前记得清空日志捕获器(单元测试里的
testLogger.clear()),避免测试间的日志污染。 - 用AssertJ的断言语法比JUnit原生断言更灵活易读,推荐使用。
内容的提问来源于stack exchange,提问作者kaviya .P
相关产品推荐
相关产品推荐

