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
相关产品推荐
相关产品推荐

