我可以在Java中模拟受保护的超类方法调用吗?

时间:2011-10-03 13:03:21

标签: java mocking protected super superclass

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

e.g。 :

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)吗?我已经用间谍试过了,但间谍无法调用超级方法,因为我认为它超出了范围。

4 个答案:

答案 0 :(得分:3)

我认为一个模拟框架会允许你模拟protected成员,但如果你的模拟框架没有,你考虑过创建一个类的存根吗?

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

答案 1 :(得分:3)

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

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

你不关心计算方法在实践中的作用,这就是模拟的全部要点。

答案 2 :(得分:2)

你不应该嘲笑超级电话。单元测试旨在测试类的功能,祖先类的功能是该功能的一部分

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

答案 3 :(得分:1)

不幸的是,我不认为有一种简单的方法来模仿super.calculate

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

这是使用继承将类比你想要的更紧密地耦合的许多例子之一。

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

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

我认为你必须在增加calculate()的可见性之间做出选择,如上所述,并编写一个干净的单元测试 - 我认为你不能同时拥有它们。