1

假设我有一个包含很多方法的接口,我想模拟这些方法进行测试,并且假设我不需要它来做任何事情,我只需要被测对象有一个实例。例如,我想对某些代码运行一些性能测试/基准测试,并且不希望此接口上的方法做出贡献。

有很多工具可以轻松做到这一点,例如

Interface mock = Mockito.mock(Interface.class);
ObjectUnderTest obj = ...
obj.setItem(mock);

管他呢。

但是,它们都带有一些我宁愿避免的运行时开销:

  • Mockito 记录所有调用,存储参数以供稍后验证
  • JMock 和其他人(我相信)要求您定义他们要做什么(没什么大不了的),然后执行通过各种代理来实际调用该方法。
  • 好老的 java.lang.reflect.Proxy 和朋友们在到达要调用的方法之前,都至少在堆栈上进行了几次方法调用,通常是反射性的。

(我愿意纠正这些例子的任何细节,但我相信原则是成立的。)

我的目标是接口的“真正的”无操作实现,例如我可以手动编写所有返回null的 ,false0. 但是,如果我感到懒惰并且界面有很多方法,那也无济于事。那么,如何在运行时生成和实例化任意接口的这种无操作实现呢?

有一些可用的工具,如 Powermock、CGLib,它们使用字节码生成,但只是作为更大的模拟/代理上下文的一部分,我还没有弄清楚要从内部挑选什么。

好的,所以这个例子可能有点做作,我怀疑代理会对时间产生太大的影响,但我现在很好奇如何生成这样的类。在 CGLib、ASM 中容易吗?


编辑:是的,这是过早的优化,没有真正需要这样做。在写完这个问题之后,我认为最后一句话并没有完全说明我对原则上如何做到这一点更感兴趣,以及与我给出的实际用例相比,动态类生成的简单方法。也许从一开始就措辞不佳。

4

2 回答 2

3

不确定这是否是您要查找的内容,但 Eclipse 中的“新类”向导允许您构建新类并指定超类和/或接口。如果你让它,它将自动编码所有接口/抽象方法的虚拟实现(返回null除非void)。做起来很轻松。

我怀疑其他“大牌”IDE,例如 NetBeans 和 Idea,也有类似的设施。


编辑:

再次查看您的问题,我想知道为什么您在处理测试类时会担心自动代理的性能。在我看来,如果性能是一个问题,你应该测试“真正的”功能,如果你正在处理大部分未实现的类,那么你不应该处于性能很重要的测试环境中。

于 2010-06-22T11:41:06.860 回答
0

构建实用程序需要一些工作,但对于没有“边缘情况”(注释等)的基本 vanilla Java 接口来说,使用 Javassist 代码生成在运行时以文本方式创建一个类,该类实现每个接口上定义的方法。这与 Javassist ProxyFactory(或 CGLib Enhancer)代理对象不同,后者仍然有一些间接层。我认为直接字节码生成模式在生成的类中不会有任何开销。如果你有勇气,你也可以潜入 ASM 做同样的事情。

于 2012-02-14T04:26:47.600 回答