【问题标题】:How to test protected methods of abstract class using JUnit and JMock如何使用 JUnit 和 JMock 测试抽象类的受保护方法
【发布时间】:2019-10-27 19:27:10
【问题描述】:

我有这样的情况——我有接口(比如MyInterface)和简单的部分实现(AbstractMyInterface)。后者添加了一些我想测试的受保护方法。

目前我只是手动编写了一个模拟对象,它扩展了AbstractMyInterface 并将受保护的方法导出为公共的。有没有更简单的方法——例如使用 JMock+scripting?

【问题讨论】:

    标签: java unit-testing junit jmock


    【解决方案1】:

    我看不出用 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

    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 {
    }
    

    【讨论】:

    • 除了测试中未使用的存根列表越来越多之外没有问题。
    • 在您的代码 sn-p 中,我想您忘记将 abstract 修饰符添加到您的 AbstractClass :)
    • 不使用内部类,您可以简单地将instanceToTest 初始化为new AbstractClass(){};
    【解决方案2】:

    只是一个建议,

    如果我们不测试受保护的方法,我们可以使用公共方法来覆盖那些受保护的方法吗?

    如果不是,是不是因为protected方法太复杂,重构把复杂的东西提取到一个新的对象中,它提供了公共接口,在一些公共方法中只留下旧对象一个私有对象。

    稍后将在新对象上进行测试。

    这个blog post 可能会有所帮助。

    【讨论】:

    • 否 - 受保护的方法非常简单,但它们被纳入公共 API(简单发布/订阅模型的一部分)。该部分由公共方法使用,但为了测试它是否有效,我需要访问受保护的部分。截至发布 - 虽然我同意不应测试私有方法,但其他人使用受保护的方法。
    • 公有方法需要访问公有API,被保护方法封装,看来这个类有两个任务。设计一个包装器类来隐藏公共 API,并设计一个用户类来使用包装器提供的服务。因此,即使要更改 API,也不会对可能充满逻辑的用户类造成伤害。我从对凌乱的十年生命周期的 c 代码进行单元测试中学到的是,如果很难进行单元测试,那就放弃吧,重构代码是一种简单且良好的投资回报率方法。
    • Chris Zheng:您能否为使用发布订阅的简单代码展示这一点?公共方法应该只注册/注销观察者,而受保护的方法只触发各种事件(循环观察者设置并发送通知事件)。我看不到可以按照您描述的方式进行操作并且不会违反 KISS 规则的解决方案。
    • 好的,我明白了。如果这就是你所拥有的一切,那么创建一个新类似乎并不简单。但它是如此简单,可以通过公共接口进行测试。模拟这个对象,并通过公共接口测试,检查是否发送了通知事件。
    【解决方案3】:

    您可以为接口(或抽象类)创建一个抽象测试用例。然后为你的接口(或抽象类)的每个具体实现创建一个具体的测试用例,扩展你的抽象测试用例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-04
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 2011-06-27
      • 2015-08-02
      相关资源
      最近更新 更多