【问题标题】:Can I mock a protected superclass method call in Java?我可以在 Java 中模拟受保护的超类方法调用吗?
【发布时间】:2011-11-29 22:11:48
【问题描述】:

我偶然发现了一个模拟从超类调用受保护方法的测试问题。

例如:

public class A extends B {
    @Override
    protected int calculate(int x, int y) {
         int result = super.calculate(x, y);
         result += 10;
         return result;
    } 
}

那么是否可以通过任何方式模拟super.calcluate(x,y)?我已经用 spy 尝试过,但 spy 无法调用超级方法,因为我认为它超出了范围。

【问题讨论】:

    标签: java mocking protected super superclass


    【解决方案1】:

    我想一个模拟框架可以让你模拟 protected 成员,但如果你的模拟框架不允许,你是否考虑过创建一个类的存根?

    public class AStub extends A {
        @Override
        protected int calculate(int x, int y) {
            // do stub calculation 
            return calculation;
        }
    }
    

    【讨论】:

    • 这有什么帮助?听起来OP想在A::calculate()B::calculate()之间插入一个模拟方法,以便前者调用模拟方法而不是从B继承的方法。覆盖A::calculate() 完全绕过这两种方法。话虽如此,最初的需求对我来说似乎是一种代码味道。也许A 应该组成B 而不是扩展它。
    【解决方案2】:

    当你模拟一个对象时,你并不关心它的实现。您只需添加对调用哪个方法的期望。

    如果您模拟 A,那么您的期望会说“我希望使用参数 2 和 3 调用 A 上的方法计算,结果将为 15”。

    你不在乎计算方法在实践中做了什么,这就是模拟的全部意义。

    【讨论】:

      【解决方案3】:

      您不应该嘲笑对 super 的调用。单元测试旨在测试类的功能,而祖先类的功能是该功能的一部分

      唯一需要模拟超类的时候是祖先类表现不佳 - 例如初始化外部类作为其自身初始化的一部分(没有依赖注入的投影)或访问外部资源(没有投影依赖注入)。如果您有权访问祖先类,请对其进行重构以消除这些问题。

      【讨论】:

        【解决方案4】:

        不幸的是,我认为没有简单的方法可以模拟super.calculate

        我可以看到您想为 A 编写一个不依赖 B 的“干净”单元测试,这是一个合理的目标。但是,如果 A 在其超类上调用受保护的方法,Java 就很难将这两个类解耦。

        这是使用继承比您想要的更紧密地结合类的众多示例之一。

        理想情况下,A 会包装 B 而不是扩展它(即使用组合而不是继承),然后调用myB.calculate 而不是super.calculate

        两个类都可以实现相同的接口(例如Calculable),以允许客户端以多态方式处理它们。这种方法将要求 B.calculate 是公开的,或者至少是包公开的。您的单元测试可以设置一个包装模拟 B 的 A,从而解决您的问题。

        我认为您必须在增加calculate() 的可见性(如上所述)和编写干净的单元测试之间做出选择——我认为您不能两者兼得。

        【讨论】:

        • 是的,我认为这是我将AB 作为一个单元进行测试的时候之一,特别是如果A 是抽象的。许多人会告诉您避免直接测试/模拟受保护的方法,因为它们依赖于实现细节,但我经常这样做,因为单元测试应该练习这些细节。我认为这取决于你的分离有多干净,但如果它那么干净,你可能应该使用组合来代替,就像你说的那样。
        猜你喜欢
        • 2018-10-12
        • 2010-10-11
        • 2011-05-18
        • 2011-08-10
        • 1970-01-01
        • 1970-01-01
        • 2012-01-08
        • 2023-04-09
        相关资源
        最近更新 更多