我正在尝试为我的项目编写测试,让我知道,我假设通过反思,我正在测试的类可能调用特定方法。
请注意以下示例代码:
class A implements SomeInterface {
@Override
public process(B bInstance) {
if (Math.rand() < 0.5)
bInstance.thirdPartyCall(param1, param2); //I need this!
}
}
类重写了一个方法进程(...),它可以从传递给process()的一个对象中调用一个方法。我需要我的测试来确定所讨论的类是否已被编码为包括对B()的任何调用,以及参数是什么。如果我们只能将调用作为字符串,我希望能够使用它。
我们拥有覆盖A()的类和包含B()的类的所有源代码,但我们需要将其动态化以备将来维护。因为我们需要它是动态的,所以我不能只创建一个模拟因为我不知道我的模拟设置是否会触及从bInstance调用方法的代码。
答案 0 :(得分:2)
你无法通过反射来做到这一点,因为从广义上讲,反射可以告诉你关于类的签名,但是没有给你任何关于它们实现的信息。
为了完成您的工作,您需要查看字节码,并查看每个方法定义中出现的invokevirtual
(或invokestatic
静态方法)代码。使用它你可以建立一种字典来确定调用什么。 (据推测,这就是IDE依赖于“查找用法”功能。)
对于您自己定义的“独立”方法,这可能就足够了。但是,对于覆盖或实现其他地方定义的方法的方法来说会更棘手 - 例如,如果您定义自己的Runnable
或Map
子类。通过检查字节码来了解方法调用的具体实现是不容易的(甚至可能是不可能的),因此您无法确定是否您的地图的{{1}如果调用者只是引用了get()
,则会被调用。同样,如果您实施Map
,则您的班级Runnable
不太可能直接致电A
;该调用可能来自标准库中的某个位置(例如,在run
或ExecutorService
中),因此您必须在类路径上的所有内容上构建一个非常大的传递调用映射,不只是你自己的代码。
另外,当然,要将它带回到您的初始点 - 您根本无法检测反射呼叫。 Thread.start()
可以从静态分析角度调用任何内容。
我认为您的意图很好,但除非您能够找到现有的库,否则为您的测试开发此类“覆盖”指标是不值得的。