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

使用@InjectMocks模拟ProcessorFactory组件在测试中失效问题排查

问题原因分析
  • Mockito @InjectMocks的实例创建逻辑:@InjectMocks默认通过无参构造函数(若存在)反射生成实例,不会主动调用你定义的带List<Processor>参数的构造函数,这直接导致静态processorCache未被初始化——构造函数根本没执行。
  • 静态缓存与依赖注入的冲突:运行时Spring会管理ProcessorFactory的生命周期,主动调用带参构造函数完成注入;但测试中使用Mockito时,它不参与Spring上下文管理,只是单纯实例化对象,自然不会触发Spring的注入逻辑。
解决方案

方案1:改用Spring Boot测试框架,让Spring管理测试上下文

放弃纯Mockito测试,使用@SpringBootTest或@WebMvcTest(针对Web层),配合@MockBean替换需要模拟的Processor子类:

@SpringBootTest
class ProcessorFactoryTest {
    @Autowired
    private ProcessorFactory processorFactory;

    // 模拟特定Processor子类
    @MockBean
    private ProcessorType1 processorType1;

    @Test
    void testGetProcessor() {
        // 给定模拟逻辑
        when(processorType1.getType()).thenReturn(Type.TYPE1);
        // 执行测试
        Processor processor = processorFactory.getProcessor(Type.TYPE1);
        assertNotNull(processor);
    }
}

这样Spring会正常初始化ProcessorFactory,调用带参构造函数填充List<Processor>,同时用@MockBean替换真实的ProcessorType1实例。

方案2:调整ProcessorFactory的初始化逻辑,兼容Mockito测试

给ProcessorFactory添加一个初始化方法,手动触发缓存加载,测试时主动调用:

@Component
public class ProcessorFactory {
    private static final Map<Type, Processor> processorCache = new HashMap<>();

    // 构造函数注入
    public ProcessorFactory(List<Processor> processors) {
        initCache(processors);
    }

    // 暴露初始化方法给测试用
    public static void initCache(List<Processor> processors) {
        processorCache.clear();
        processors.forEach(p -> processorCache.put(p.getType(), p));
    }

    // 静态获取方法
    public static Processor getProcessor(Type type) {
        return processorCache.get(type);
    }
}

测试类中手动初始化缓存:

class ProcessorFactoryTest {
    @Mock
    private ProcessorType1 processorType1;

    private ProcessorFactory processorFactory;

    @BeforeEach
    void setUp() {
        // 手动构造实例并初始化缓存
        processorFactory = new ProcessorFactory(List.of(processorType1));
        // 或者直接调用静态初始化方法
        ProcessorFactory.initCache(List.of(processorType1));
        when(processorType1.getType()).thenReturn(Type.TYPE1);
    }

    @Test
    void testGetProcessor() {
        Processor processor = ProcessorFactory.getProcessor(Type.TYPE1);
        assertEquals(processorType1, processor);
    }
}

这种方式不需要Spring上下文,纯Mockito即可完成测试,同时兼容原有运行时逻辑。

方案3:重构ProcessorFactory,去掉静态依赖(推荐)

静态缓存会导致测试难维护,建议把processorCache改为实例变量,让ProcessorFactory成为普通Spring组件,通过依赖注入使用:

@Component
public class ProcessorFactory {
    private final Map<Type, Processor> processorCache;

    public ProcessorFactory(List<Processor> processors) {
        this.processorCache = processors.stream()
                .collect(Collectors.toMap(Processor::getType, p -> p));
    }

    // 去掉static,改成实例方法
    public Processor getProcessor(Type type) {
        return processorCache.get(type);
    }
}

然后MyService中通过@Autowired注入ProcessorFactory:

@Service
public class MyService {
    private final ProcessorFactory processorFactory;

    @Autowired
    public MyService(ProcessorFactory processorFactory) {
        this.processorFactory = processorFactory;
    }

    public void doSomething(Type type) {
        Processor processor = processorFactory.getProcessor(type);
        // 执行逻辑
    }
}

测试时用@InjectMocks或Spring注入都能正常工作,彻底解决静态与依赖注入的冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:25:19