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时,不必进行太多重构。如果您经常这样做,而每次都没有受到重构遗留问题的约束,那么您的测试中就会有很多“隐藏”的依赖项。垃圾散开了!