我正在尝试为我的项目编写一个测试,让我知道(我假设通过反射)我正在测试的类是否可能调用特定方法。
请注意以下示例代码:
class A implements SomeInterface {
@Override
public process(B bInstance) {
if (Math.rand() < 0.5)
bInstance.thirdPartyCall(param1, param2); //I need this!
}
}
类重写方法 process(...),该方法可能从传递到 process() 的对象之一调用方法。我需要进行测试来查明相关类是否已编码为包含对 B() 的任何调用,以及参数是什么。如果我们只能以字符串形式获取调用,我希望能够使用它。
我们拥有重写 A() 的类和包含 B() 的类的所有源代码,但为了将来的维护,我们需要它是动态的。由于我们需要它是动态的,所以我不能只创建一个模拟,因为我不知道我的模拟的设置是否会命中从 bInstance 调用方法的代码。
最佳答案
您无法通过反射来做到这一点,因为从广义上讲,反射可以告诉您有关类的签名,但无法提供有关其实现的任何信息。
为了完成您要做的事情,您需要查看字节码,并查看 invokevirtual
(或 invokestatic
对于静态方法)代码,这些代码出现在每个方法定义中。使用这个你可以建立一种字典来确定什么叫什么。 (大概这就是 IDE 所依赖的“查找用法”功能。)
对于您自己定义的“独立”方法,这可能就足够了。然而,对于覆盖或实现其他地方定义的方法的方法来说,事情会变得更加棘手 - 例如,如果您定义自己的 Runnable 或 Map 子类。仅通过检查字节码来了解方法调用的具体实现并不容易(甚至可能被证明是不可能的),因此您无法确定您的映射的是否得到如果调用者仅具有对 Map 的引用,则 ()
将被调用。同样,如果您确实有一个 Runnable 实现,那么您的类 A 不太可能直接调用 run ;该调用可能来自标准库中的某个地方(例如,在 ExecutorService 中或来自 Thread.start() ),因此您必须构建一个非常大型传递调用映射跨越类路径上的所有内容,而不仅仅是您自己的代码。
当然,为了将其带回初始点 - 您根本无法检测到反射调用。 Method.invoke()
从静态分析的角度来看几乎可以调用任何东西。
我认为您的意图是好的,但除非您能找到可用的现有库,否则不值得为您的测试开发这种“覆盖”指标。
关于java - 如何判断一个java方法是否可以在另一个方法中调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11849606/