2

我正在尝试为我的项目编写一个测试,让我知道,我通过反射假设我正在测试的类是否可能调用特定方法。

请注意以下示例代码:

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 调用方法的代码。

4

1 回答 1

4

您将无法通过反射来做到这一点,因为从广义上讲,反射可以告诉您有关类的签名,但不会为您提供有关其实现的任何信息。

为了做你所追求的,你需要查看字节码,并查看每个方法定义中出现的invokevirtual(或静态方法)代码。invokestatic使用它,您可以构建一种字典来确定什么叫什么。(大概这就是 IDE 所依赖的“查找用法”功能。)

对于您自己定义的“独立”方法,这可能就足够了。但是,对于覆盖或实现其他地方定义的方法的方法来说,事情会变得更加棘手 - 例如,如果您定义自己的RunnableMap子类。仅仅通过检查字节码就很难知道方法调用的具体实现是什么(甚至被证明是不可能的),所以如果调用者只是有一个参考,你不能确定你的地图是否会被调用get()Map. 同样,如果您确实有Runnable实现,那么您的类不太可能直接A调用run;该调用可能来自标准库中的某个地方(例如,在 anExecutorService或 fromThread.start()),因此您必须在类路径上的所有内容上构建一个非常大的传递调用映射,而不仅仅是您自己的代码。

另外,当然,要让它回到你的初始点——你根本无法检测到反射调用。 Method.invoke()从静态分析的角度来看,几乎可以调用任何东西。


我认为你的意图是好的,但除非你能找到一个现有的库来使用,否则为你的测试开发这种“覆盖”指标是不值得的。

于 2012-08-07T16:10:00.393 回答