【问题标题】:How to override instance/concrete class's method runtime? (e.g. reflection, cglib)如何覆盖实例/具体类的方法运行时? (例如反射,cglib)
【发布时间】:2011-10-29 02:21:25
【问题描述】:

我想做的是一种方法,可以

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

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

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

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

我认为这是可以实现的,因为 Mockito 可以进行各种方法注入运行时。
请大家给点建议,谢谢。
我图像的伪代码是这样的:

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

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

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

我的解决方法是自制 Xn 类,并将它们传递给测试用例,让 Cn.get() 符合预期
代码示例:

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

而且这种东西是分布在测试用例中的。
因此,为了减少重复代码,我想构建一个方法来生成具有指定覆盖方法的 Xn 实例进行测试。例如

X1 x1 = createAndOverride(X1);

那么,这个帖子的问题来了

【问题讨论】:

  • 你想将一个方法“注入”到一个类中?
  • 是的,但是类类型是在运行时指定的变量
  • 我认为你应该告诉我们更多关于最终结果应该是什么,因为这似乎太复杂了。也许有一种更简单的方法可以实现您想要做的事情,而无需在运行时“注入”方法。
  • 嗨 Lirik,感谢您帮助我思考我的问题,我已经重新解决了我原来的问题,如果有任何缺失的信息,请阅读并告诉我
  • 你知道给定函数应该给出的“值”或“输出”的范围吗?如果没有返回 null 的代码路径,那么为什么要测试 null

标签: java reflection overriding cglib


【解决方案1】:

您在寻找类似javassist 的东西吗?您可以在运行时检测代码并注入您的方法。我个人尽量避免字节码操作。你能不能在你的代码库中没有这些覆盖,而不是即时执行?可能是包装器之类的东西?

【讨论】:

    【解决方案2】:

    所以我认为你需要的是与 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,但请考虑上述建议,看看哪些对您有用。

    【讨论】:

    • 感谢您的建议,似乎返回 null 是此类测试的一个问题。可能我没有说清楚,null只是Class-under-test的代码路径,上面写着if(Xn.get() == null) {...}。 :)
    • @Jim,好的,那么发射功能是否不足以满足您的需求?
    猜你喜欢
    • 1970-01-01
    • 2012-07-19
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 2019-09-18
    相关资源
    最近更新 更多