单元测试中模拟构造注入的服务,关键在于用构造器注入代替字段注入,使被测类可脱离容器运行;需声明final构造参数、去除@autowired字段注入,并根据是否依赖spring特性选择纯mockito或@springboottest+@mockbean方案。

单元测试中模拟构造注入的服务,关键在于让被测类既能享受 Spring 容器管理的便利,又能在测试时绕过容器、直接构造并注入 Mock 依赖。核心不是“模拟容器”,而是**用构造器注入代替字段注入**,让类本身具备脱离容器运行的能力。
构造器注入是前提
被测类必须把所有依赖(服务、配置、参数)都声明为构造函数参数,并用 final 修饰。Spring 会自动解析这些参数(单例 Bean 由容器提供,运行时参数如 Options 由调用方传入),测试时则可手动 new 实例并传入 Mock。
- 去掉
@Autowired字段注入和private未初始化字段 - 构造器参数名要语义清晰(比如不用
s,而用storageService) - Spring 5.0+ 单构造器场景下,
@Autowired注解可省略
测试时不启动容器:纯 Mockito 方式
适用于逻辑简单、不依赖 Spring 特性(如 AOP、事务、@Value)的场景。完全在 JVM 中运行,速度快、隔离性强。
- 用
@ExtendWith(MockitoExtension.class)启用 Mockito 支持 - 用
@Mock声明依赖的 Mock 对象 - 用
new YourService(mockDep1, mockDep2)手动构造被测对象 - 或用
@InjectMocks让 Mockito 自动注入(前提是构造器参数类型唯一可匹配)
测试需加载配置或 Spring 特性:@SpringBootTest + @MockBean
当被测类用了 @Value、@Scheduled、AOP 切面、事务等 Spring 功能时,必须启动轻量级上下文。
- 用
@SpringBootTest(classes = {YourService.class, DepService.class})指定最小组件集 - 用
@MockBean替换真实 Bean(它会注册进 Spring 上下文,覆盖原 Bean) -
@Autowired获取被测实例,Spring 自动完成构造注入和配置绑定 - 避免全量启动(不加
classes属性),否则加载太慢
原型 Bean 的动态构造写法
对于 @Scope("prototype") 的 Bean(如带运行时参数的适配器),Spring 支持按需传参创建:
- 运行时:通过
applicationContext.getBean(Adapter.class, options) - 测试时:若用
@SpringBootTest,同样调用该方法传入 Mock 和测试参数 - 若用纯 Mockito,则直接
new Adapter(mockService, testOptions),无需容器参与











