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

Mockito Answer仅调用一次问题:Spring ApplicationContext.getBean模拟排查

解决Mockito中ApplicationContext.getBean多次调用时Answer仅执行一次的问题

看起来你碰到了Mockito Mock方法时的一个常见误区——明明设置了thenAnswer,但每次传不同字符串参数调用时,Answer的逻辑却只跑了一次。别担心,咱们一步步排查解决:

先排查核心原因

首先要确认:你的Answer逻辑是不是本身只生成了一次实例并缓存?比如如果在Answer里写了类似下面的代码,那不管调用多少次,都会返回同一个对象,看起来就像Answer只执行了一次:

// 错误示例:静态变量缓存了实例,导致每次返回同一个
private static SomeClass cachedBean = new SomeClass();

@Override
public SomeClass answer(InvocationOnMock invocation) throws Throwable {
    return cachedBean;
}

这种情况不是Answer没执行,而是每次都返回了同一个缓存对象,让你误以为逻辑只跑了一次。

正确的写法:每次调用都根据参数生成对应实例

要让Answer每次被调用时都能响应不同的字符串参数,你需要在answer方法里获取当前调用的参数,然后根据参数生成对应的返回值。比如:

when(applicationContext.getBean(Mockito.anyString(), Mockito.eq(SomeClass.class)))
    .thenAnswer(new Answer<SomeClass>() {
        @Override
        public SomeClass answer(InvocationOnMock invocation) throws Throwable {
            // 获取第一个参数(传入的bean名称字符串)
            String beanName = invocation.getArgument(0);
            
            // 根据不同的beanName执行不同逻辑或创建不同实例
            switch (beanName) {
                case "userService":
                    return new SomeClass("用户服务");
                case "orderService":
                    return new SomeClass("订单服务");
                default:
                    return new SomeClass("默认实例");
            }
        }
    });

如果你用的是Java 8+,可以用Lambda简化写法,更简洁:

when(applicationContext.getBean(anyString(), eq(SomeClass.class)))
    .thenAnswer(invocation -> {
        String beanName = invocation.getArgument(0);
        return new SomeClass(beanName); // 根据参数动态生成实例
    });

验证Answer是否真的只执行一次

如果你还是怀疑Answer没被多次调用,可以在answer方法里加个计数器或者日志,直接验证调用次数:

private int answerCallCount = 0;

// 在Answer逻辑里
answerCallCount++;
System.out.println("Answer已调用" + answerCallCount + "次,当前beanName:" + beanName);

运行测试后查看日志,就能明确Answer是不是真的只执行了一次,还是只是返回了相同对象导致的误解。

其他可能的排查点

  • 检查你的测试代码:是不是只实际调用了一次getBean方法?有时候我们以为调用了多次,其实代码逻辑里只触发了一次。
  • 检查Mock的初始化:是不是在测试过程中重新设置了Mock(比如多次调用when),导致后面的配置覆盖了前面的Answer?
  • 确认参数匹配是否正确:是不是某些调用的第二个参数不是SomeClass.class?只有同时匹配第一个参数是任意字符串、第二个参数是SomeClass.class的调用,才会触发这个Answer。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:05:01