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

Mockito无法识别反射场景下method.invoke()调用的问题排查

问题根因
  • 第一个测试失败的核心原因:你通过providerClass.getDeclaredMethod()单独获取并spy的fallbackMethod实例,和FallbackInvoker内部通过executor.getClass().getDeclaredMethods()遍历拿到的Method实例不是同一个对象。JDK反射API每次调用获取Method的方法都会生成新的实例,invoker实际调用的是原生Method的invoke方法,完全没有用到你spy的那个实例,自然无法触发Mockito的调用记录,验证失败。
  • 第二个测试可正常通过的原因:该测试验证的是注入给MethodInvoker的fallbackInvoker实例的方法调用,你mock的FallbackInvoker就是实际被调用的实例,所以调用记录可被Mockito正常捕获。
修复方案

推荐使用更合理的测试逻辑,直接验证业务方法的调用,而非验证JDK的Method.invoke方法调用,修改后的测试代码如下:

@Test
void theTest() throws ReflectiveOperationException {
    final JavaPlugin plugin = mock(JavaPlugin.class);
    final CommandSender sender = mock(CommandSender.class);
    final IFallbackInvoker<JavaPlugin> invoker = new FallbackInvoker<>();
    final Class<? extends TestMethodsProvider> providerClass = TestMethodsProvider.class;
    final Method method = providerClass.getDeclaredMethod("testMethodWithParam", World.class);
    // Spy业务实例而非Method元数据对象
    final TestMethodsProvider testMethodsProvider = spy((TestMethodsProvider) providerClass.getConstructors()[0]
            .newInstance(sender, plugin));
    final Mapper mapper = method.getParameters()[0].getAnnotation(Mapper.class);

    final Object result = invoker.invokeFallback(mapper, "test", World.class, testMethodsProvider);

    assertEquals(new ArrayList<>(), result);
    // 直接验证目标降级方法被调用,入参符合预期
    verify(testMethodsProvider, times(1)).testMethodWithParamArgumentFallback("test");
}

如果确实需要验证Method.invoke的调用,可通过mock FallbackInvoker的getArgumentFallbackMethods方法,让它返回你spy的fallbackMethod实例即可,不过该方案不符合单元测试的常规设计原则,更推荐上述直接验证业务方法的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 08:36:03