我偶然发现了一个测试问题,即在超类中模拟一个受保护方法的调用。
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)
吗?我已经用间谍试过了,但间谍无法调用超级方法,因为我认为它超出了范围。
答案 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()的可见性之间做出选择,如上所述,并编写一个干净的单元测试 - 我认为你不能同时拥有它们。