Java 如何使用JUnit和JMock测试抽象类的受保护方法
我有这样的情况——我有接口(比如说Java 如何使用JUnit和JMock测试抽象类的受保护方法,java,unit-testing,junit,jmock,Java,Unit Testing,Junit,Jmock,我有这样的情况——我有接口(比如说MyInterface)和简单的部分实现(AbstractMyInterface)。后者添加了一些我想测试的受保护方法 目前,我只是手工编写一个mock对象,它扩展了AbstractMyInterface,并将受保护的方法导出为public。有没有一种更简单的方法可以做到这一点——例如使用JMock+脚本?我看不出用JUnit测试受保护的方法有任何问题。只要测试的包结构镜像源树结构,测试就可以看到私有以外的方法 当然,若要测试的实现是抽象的,那个么您必须自己创建
MyInterface
)和简单的部分实现(AbstractMyInterface
)。后者添加了一些我想测试的受保护方法
目前,我只是手工编写一个mock对象,它扩展了
AbstractMyInterface
,并将受保护的方法导出为public。有没有一种更简单的方法可以做到这一点——例如使用JMock+脚本?我看不出用JUnit测试受保护的方法有任何问题。只要测试的包结构镜像源树结构,测试就可以看到私有以外的方法
当然,若要测试的实现是抽象的,那个么您必须自己创建被测试类的普通子类(或者,若更适合您的目的,可以通过一些模拟库来创建)。同样在这种情况下,不需要为调用受保护的可见性方法创建公共方法层。仅对于私有方法,此策略不起作用。但通常需要测试私有方法是设计问题的标志
例如:
要测试的类位于src/mypackage/AbstractClass.java
包我的包
/** This could as well implement some interface,
but that does not change a thing */
public abstract class AbstractClass {
protected int returnsOne() {
return 1;
}
}
和位于tests/mypackage/AbstractClassTest.java的test
package mypackage;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
public class AbstractClassTest {
@Test
public void returnsOneReturnsOne() {
AbstractClass instanceToTest = new AbstractClassTestable();
assertEquals(1, instanceToTest.returnsOne());
}
}
/** This is needed, because we cannot construct abstract class directly */
class AbstractClassTestable extends AbstractClass {
}
您可以为接口(或抽象类)创建抽象测试用例。然后为接口(或抽象类)的每个具体实现创建一个具体的测试用例,扩展抽象测试用例。只是一个建议 如果我们不测试受保护的方法,我们可以使用公共方法覆盖这些受保护的方法吗 如果不是,是因为受保护的方法过于复杂,重构以将复杂的内容提取到新对象,该对象提供公共接口,而旧对象在某些公共方法中仅保留一个私有对象 稍后将对新对象进行测试
这可能会有帮助。除了我在测试中有越来越多的未使用存根之外,没有问题。在您的代码片段中,我认为您忘记了向您的AbstractClass:)添加
abstract
修饰符,而不是使用内部类,您可以简单地将instanceToTest
初始化为new AbstractClass(){}代码>否-受保护的方法非常简单,但它们被整合到公共API(简单发布/订阅模型的一部分)中。该部件由公共方法使用,但为了测试它是否工作,我需要访问受保护的部件。虽然我同意私有方法不应该被测试,但是受保护的方法被其他人使用。公共方法需要访问由受保护的方法包装的公共API,看起来这个类有两个任务。设计一个包装器类来隐藏公共API,并设计一个用户类来使用包装器提供的服务。因此,即使API要更改,也不会对可能充满逻辑的用户类造成伤害。我从为凌乱的十年生命周期的c代码进行单元测试中学到的是,如果很难进行单元测试,那么离开它,重构代码是一种简单而好的RoI方法。Chris Zheng:对于使用发布-订阅的简单代码,你能证明这一点吗?公共方法应该只注册/取消注册观察者,而受保护的方法只触发各种事件(在观察者设置和发送通知事件上循环)。我看不到解决方案,它可以按照你们描述的方式来做,并且不会违反接吻规则。好的,我明白了。如果这就是您所拥有的,那么创建一个新类似乎并不简单。但它非常简单,可以通过公共接口进行测试。模拟此对象,并通过公共接口进行测试,检查是否发送了通知事件。