You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:41:39