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

单元测试中如何在注入服务类构造函数执行前模拟值?

问题分析

你的核心问题是Spring上下文初始化时会优先创建MyService实例并执行构造函数,而@BeforeEach注解的init()方法是在MyService实例化完成后、测试方法执行前才运行,导致mockValue()设置的模拟值无法被构造函数中的myRepository.getValue()获取,最终触发空值异常。

解决方案

方案1:手动创建Mock与实例(推荐,测试效率更高)

完全脱离Spring自动注入,直接用Mockito创建MyRepository的Mock对象,在实例化MyService之前就设置好模拟返回值,彻底控制初始化顺序:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class MyServiceTest {

    private MyService myService;
    private MyRepository mockMyRepository;

    @BeforeEach
    void init() {
        // 创建MyRepository的Mock对象
        mockMyRepository = mock(MyRepository.class);
        // 在实例化MyService前设置模拟值
        when(mockMyRepository.getValue("login")).thenReturn("login_value");
        when(mockMyRepository.getValue("password")).thenReturn("password_value");
        // 手动初始化MyService
        myService = new MyService(mockMyRepository);
    }

    // 编写你的测试方法...
}

这种方式不需要启动Spring上下文,测试执行速度更快,且完全避免了Spring初始化顺序带来的问题。

方案2:通过测试配置类提前准备Mock(依赖Spring上下文场景)

如果必须依赖Spring上下文进行测试,可以自定义测试配置类,在配置类中提前创建并配置好MyRepository的Mock对象,确保MyService构造函数执行时能拿到有效模拟值:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ContextConfiguration(classes = MyServiceTest.TestConfig.class)
class MyServiceTest {

    @Autowired
    private MyService myService;

    // 自定义测试配置类
    @Configuration
    static class TestConfig {
        @Bean
        public MyRepository myRepository() {
            MyRepository mockRepo = mock(MyRepository.class);
            // 提前设置模拟返回值
            when(mockRepo.getValue("login")).thenReturn("login_value");
            when(mockRepo.getValue("password")).thenReturn("password_value");
            return mockRepo;
        }

        @Bean
        public MyService myService(MyRepository myRepository) {
            return new MyService(myRepository);
        }
    }

    // 编写你的测试方法...
}

Spring上下文初始化时,会先加载TestConfig中的MyRepository Bean,此时模拟值已经设置完成,后续创建MyService时构造函数就能正常获取到值。

内容的提问来源于stack exchange,提问作者Laziz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:51:15