如何覆盖实例/具体类的方法运行时? (例如,反射,cglib)

时间:2011-10-29 02:21:26

标签: java reflection override cglib

我想做的是一种可以

的方法
  • 生成Class X的实例(在arg中传递的类变量)和
  • 覆盖其中一些方法

更具体地说,我要覆盖的父类X包含

  • 不包含默认构造函数(例如,所有带args的构造函数)
  • 构造函数在同一个类中调用非私有方法

最初我认为使用反射或类似的东西很简单, 然后我发现实施我的要求存在限制。

我认为这是可以实现的,因为Mockito可以做各种方法注入运行时 请有人给一些建议,谢谢 伪代码I图像是这样的:

createAndOverride(Class X) {
    X newObj = X.newInstance(args) {
        @override
        methodOfX(args2) {
            ...
        }
    }
    return newObj;
}
  • 原始问题情景

我打算测试一个Class,它有几个方法调用X1.get(),X2.get(),X3.get()
在某些测试用例中,我需要让Xn.get()返回我可以控制测试的内容(例如null) 由于以下限制:

  • 但是由于对JMock 1.0的模拟工具限制(我没有控制:(),所以我不能只是简单地模拟Xn.get()来返回“someSpecifiedObjects”
  • Xn没有调用非私有成员的空构造函数和构造函数

我的解决方法是自制的Xn Class并将它们传递给测试用例以让Cn.get()得到预期。 代码示例:

ClassToTest.SomeMethod(new X1() {
    @override
    get() {
        return someSpecifiedObjects;
    }
});

这种事情在测试案例中得到了扩展。
因此,为了减少重复代码,我想构建一个方法来生成带有指定覆盖方法的Xn实例进行测试。例如

X1 x1 = createAndOverride(X1);

然后,这篇文章的问题来了

2 个答案:

答案 0 :(得分:1)

你正在寻找javassist之类的东西吗?您可以在运行时检测代码并注入方法。我个人尽量避免字节码操作。您是否可以在代码库中使用这些覆盖而不是动态执行?可能像包装纸一样?

答案 1 :(得分:0)

所以我认为你需要的是与C#的Reflection.Emit

类似的功能

虽然我自己没有这样做,但我认为您应该能够使用反射/发射和动态类型创建来实现您所需要的。但是,我还是要提一下,如果你试图测试的“功能”并不是你正在测试的函数的代码路径,那么你可能根本就不应该测试它。例如:

SomeObjectInterface get()
{
    if(_someObjectStateIsSet)
    {
        // Return a concrete implementation A
        return new ConcreteImplA();
    }
    else
    {
        // Return a concrete implementation B
        return new ConcreteImplB();
    }
}

在这种情况下,get没有返回null的代码路径,因此您不需要测试null。我不确定我是否100%正确理解你的问题,特别是你为null进行测试的原因,但考虑上述建议,看看哪些对你有用。