Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将测试驱动开发引入遗留代码_Java_Oop_Tdd_Design Principles - Fatal编程技术网

Java 将测试驱动开发引入遗留代码

Java 将测试驱动开发引入遗留代码,java,oop,tdd,design-principles,Java,Oop,Tdd,Design Principles,给定:一个LegacyControllerClass,它扩展了一个MonsterFrameworkClass(这是一个非常恶心的框架的一部分,人们已经生活了很多年)。框架类具有很多魔力,从默认构造函数中的大量逻辑到反射加载类的静态块 LegacyControllerClass中有很多生命周期方法,这些方法会改变全局状态。execute() public class LegacyControllerClass extends MonsterFrameworkClass { //Life-c

给定:一个
LegacyControllerClass
,它扩展了一个
MonsterFrameworkClass
(这是一个非常恶心的框架的一部分,人们已经生活了很多年)。框架类具有很多魔力,从默认构造函数中的大量逻辑到反射加载类的静态块

LegacyControllerClass
中有很多生命周期方法,这些方法会改变全局状态。
execute()

public class LegacyControllerClass extends MonsterFrameworkClass {

   //Life-cycle method
   public void validate(){...}

   //Life-cycle method
   public void preExecute() {...}

   //Life-cycle method
   public void execute() {
       //oodles of legacy code here:
       //    examples: call static methods of 'Util' classes
       //              lots of new X().y(..)
       //              call databases, services
       //              Even call super.execute()!!
       //              More rubbish
       //              More rubbish 
   }
}
好的,现在动作场景是execute()方法。我向这些穷人介绍测试驱动开发,通过测试驱动一个他们称之为“故事”的项目。“故事”涉及将错误消息添加到responseProperties,以便视图(jsp)能够读取并显示它。伪代码类似于:

if (error) {
    Build the error message
    Add the error message into the responseProperties
}
不幸的是,此代码必须在
execute()
方法中的垃圾之间进行沙盘切换

我的问题是:我能做的最好的事情是什么? 我能想出的解决办法是:

  • 提取两种方法
    rubbish1()
    rubbish2()
  • 在我的测试代码中用任何期望值将它们剔除(例如;-设置错误标志)
  • 将我的代码放在
    rubbish1()
    rubbish2()之间
  • 我开始以这种方式实现它,但是
    MonsterFrameworkClass
    真的阻碍了我:比如静态加载,加载随机属性文件的
    ResourceBundle
    的构造函数魔术,等等

    是否有其他处理相同问题的方法


    小小的免责声明:我肯定会买下Michael Feather的“使用遗留代码”并一饮而尽,但这似乎是一个唾手可得的成果。

    垃圾重构为方法很好。现在,您可以下载Powermock来模拟代码中所有的糟糕的垃圾。完成模拟后,可以测试代码

    如果你不给这个怪物添加任何东西,那就更好了。通过为新东西编写自己的类,您可以将您的功能组合到
    MonstrosityRubbish
    (或其他任何内容)

    最重要的是不要接触任何遗留代码,如果可能的话,您可以将代码组合到其中

    因此,在代码中:

    private MyShinyClass yourShinyObject; // init
    
    public void execute(Param param0) {
        rubbish1();
        yourShinyObject.handleError(param0);
        rubbish2();
    }
    
    public class MyShinyClass {
    
        public void handleError(Param param0) {
            // your code here
        }
    }
    
    如果你能像这样写你的新东西,你将只依赖于
    Param
    ,它可以被模仿/存根,你的代码可以被测试,而不会让你毛骨悚然

    如果您能够以函数式的方式编写它,那么就更好了,这样您就不必在单独的代码中操纵
    responseProperties

    public void execute(Param param0) {
        rubbish1();
        responseProperties.add(yourShinyObject.fetchErrors(param0));
        rubbish2();
    }
    
    public class MyShinyClass {
    
        public List<HopelessError> fetchErrors(Param param0) {
            // your code here
        }
    }
    
    public void execute(Param param0){
    垃圾1();
    add(yourShinyObject.fetchErrors(param0));
    垃圾2();
    }
    公共类MyShinyClass{
    公共列表获取错误(Param param0){
    //你的代码在这里
    }
    }
    

    当然
    execute()。我肯定会读到powermock:你认为它可以解决超类的静态库负载、资源包声明等问题吗?是的。Powermock基于Mockito构建,它能够处理Mockito无法处理的所有垃圾。它们可以互操作,因此当您开始使用Powermock时,不必进行太多重构。如果您经常这样做,而每次都没有受到重构遗留问题的约束,那么您的测试中就会有很多“隐藏”的依赖项。垃圾散开了!