如何判断一个java方法是否可以在另一个方法中调用

如何判断一个java方法是否可以在另一个方法中调用,java,testing,reflection,Java,Testing,Reflection,我正试图为我的项目编写一个测试,通过反射我假设,如果我测试的类可能调用一个特定的方法,它会让我知道 请注意下面的示例代码: class A implements SomeInterface { @Override public process(B bInstance) { if (Math.rand() < 0.5) bInstance.thirdPartyCall(param1, param2); //I need this!

我正试图为我的项目编写一个测试,通过反射我假设,如果我测试的类可能调用一个特定的方法,它会让我知道

请注意下面的示例代码:

class A implements SomeInterface {
    @Override
    public process(B bInstance) {
        if (Math.rand() < 0.5)
            bInstance.thirdPartyCall(param1, param2); //I need this!
    }
}
A类实现了SomeInterface{
@凌驾
公共程序(B){
if(Math.rand()<0.5)
bInstance.thirdPartyCall(param1,param2);//我需要这个!
}
}
该类重写了一个方法进程(…),该进程可能会从传递到process()中的一个对象调用一个方法。我需要进行测试,以确定所讨论的类是否已编码为包含对B()的任何调用,以及参数是什么。如果我们只能将调用作为字符串,我希望能够处理它


我们有覆盖A()的类和包含B()的类的所有源代码,但是为了将来的维护,我们需要动态的源代码。因为我们需要动态的,所以我不能只创建一个mock,因为我不知道mock的设置是否会影响从BinInstance调用方法的代码。

你不能通过反射来实现这一点,因为广义上说,反射可以告诉你类的签名,但却不能告诉你它们的实现

为了完成您想要的任务,您需要查看字节码,并查看出现在每个方法定义中的
invokevirtual
(或
invokestatic
,对于静态方法)。使用它,你可以建立一种字典,确定什么叫什么。(这大概就是IDE“查找用法”功能所依赖的。)

对于您自己定义的“独立”方法,这可能就足够了。然而,对于重写或实现在别处定义的方法来说,事情会变得更加棘手——例如,如果您定义自己的
Runnable
,或者
Map
子类。仅仅通过检查字节码就不可能知道方法调用的具体实现是什么(甚至可能证明是不可能的),因此如果调用方只是引用了
map
,您无法确定是否会调用映射的
get()
。同样,如果您有一个
Runnable
实现,那么您的类
a
不太可能直接调用
run
;该调用可能来自标准库中的某个地方(例如
ExecutorService
Thread.start()
),因此您必须跨类路径上的所有内容建立一个非常大的可传递调用映射,而不仅仅是您自己的代码

当然,再加上,把它带回到你的初始点——你根本无法检测到反射呼叫
Method.invoke()
可以从静态分析的角度调用任何东西



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

你不能通过反射来实现这一点,因为广义上说,反射可以告诉你类的特征,但是没有提供任何关于它们实现的信息

为了完成您想要的任务,您需要查看字节码,并查看出现在每个方法定义中的
invokevirtual
(或
invokestatic
,对于静态方法)。使用它,你可以建立一种字典,确定什么叫什么。(这大概就是IDE“查找用法”功能所依赖的。)

对于您自己定义的“独立”方法,这可能就足够了。然而,对于重写或实现在别处定义的方法来说,事情会变得更加棘手——例如,如果您定义自己的
Runnable
,或者
Map
子类。仅仅通过检查字节码就不可能知道方法调用的具体实现是什么(甚至可能证明是不可能的),因此如果调用方只是引用了
map
,您无法确定是否会调用映射的
get()
。同样,如果您有一个
Runnable
实现,那么您的类
a
不太可能直接调用
run
;该调用可能来自标准库中的某个地方(例如
ExecutorService
Thread.start()
),因此您必须跨类路径上的所有内容建立一个非常大的可传递调用映射,而不仅仅是您自己的代码

当然,再加上,把它带回到你的初始点——你根本无法检测到反射呼叫
Method.invoke()
可以从静态分析的角度调用任何东西



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

你测试的代码真的是随机的吗?我很难理解为什么您需要知道可能会调用一个方法。实际代码不是随机的,但在实际代码中,可能有一些逻辑分支是测试不知道的,这取决于对象的状态或传递给它的参数。本例中的随机性意味着,就我们所知,第三方方法调用的机会也可能是随机的。您正在测试的代码真的是随机的吗?我很难理解为什么您需要知道可能会调用一个方法。实际代码不是随机的,但在实际代码中,可能有一些逻辑分支是测试不知道的,这取决于对象的状态或传递给它的参数。本例中的随机性意味着,就我们所知,第三方方法调用的机会也可能是随机的。谢谢您的回答。我们决定走视察路线