繁体   English   中英

如何验证 java.lang.reflect.Method 仅从反射已知被调用在 object

[英]How to verify a java.lang.reflect.Method known only from reflection was called on an object

给定通过反射获得的 java.lang.reflect.Method object,我如何测试在给定的 object 上调用了此方法?

这是一个示例代码:

MyClass obj = mock(MyClass.class);
injectInTestedObject(obj, testedObj);

String myMethodIWantToCheckName = retrieveMethodNameBySomeMeans();
Method myMethodIWantToCheck =
  Arrays.asList(MyClass.class.getMethods())
    .stream()
    .filter(method -> method.getName().equals(myMethodIWantToCheckName))
    .findFirst()
    .get();

现在我想检查是否在obj上调用了myMethodIWantToCheck

基本上它与 Mockito 的verify功能相同,但在编译时不知道该方法。

有什么办法吗? 任何图书馆已经实现了这个?

不,显然没有简单的方法可以仅使用 Java SE 提供的库。 我对此感到非常高兴!

天真的方法

让我们想象一下,您要实现的目标实际上是可能的,并且在java.lang.reflect中支持操作。 提供这样的功能需要什么样的信息和机制? 如果一个人应该能够在任何时候检索某个方法是否已经被调用(在某个对象上)至少一次(没有“开始分隔符”),则需要 Java 虚拟机来跟踪任何调用; 有效地强制它保留所有创建的堆栈帧,引入这样的起始分隔符可能会减少运行时开销,但仍需要极其复杂的堆栈帧审计形式。 内置在每个 JVM 中。

Mockito 是如何做到的

但是,嘿,Mockito 能够提供这样的功能,对吧? 确实,但我认为你低估了他们这样做的方式的复杂性。

首先,您的方法和 Mockito 的方法之间存在一个非常重要的概念差异。 在查看Mockito 网站上的第一个示例时,已经很明显了:

import static org.mockito.Mockito.*;

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();

框架的用户总是必须首先模拟感兴趣的类型; 要么明确地喜欢这里,要么通过使用注释以更隐含的方式。 由于我对 Mockito 框架不是很熟悉,因此可能有更优雅的方法可以做到这一点; 但这一切都归结为同一个概念。

但是“模拟类型”甚至意味着什么,它应该有什么用处? 实际上,Mockito 必须以某种方式拦截对 mocking 方法(或其他机制)返回的 object 进行的任何调用。 幸运的是(记住这篇文章的开头),Mockito 不能直接这样做,所以开发人员必须想出别的办法:在运行时动态创建新类型,不仅将方法调用委托给实际实现,但它也跟踪在该特定类型上调用的方法。

查看框架的源代码,似乎真正的魔力发生在org.mockito.internal.creation.bytebuddy package 中。 SubclassBytecodeGenerator中,您可以找到 Mockito 的类型创建逻辑。 正如 package 名称已经暗示的那样,Mockito 使用Byte Buddy 框架进行字节码生成和加载过程。

图书馆支持

正如您还要求提供一个可以用来实现相同行为的库:据我所知,那里没有真正知名的库

老实说:我对这种情况并不感到惊讶。 我的意思是,一个人应该使用这样的图书馆做什么? 检查方法是否被调用是测试中应该做的事情; 其他用例非常有限。

是的。 我想你的选择非常有限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM