我遇到了一些java代码,其中公共构造函数调用一个包私有构造函数,其中包含一堆新的运算符来创建新对象.
public class Thing {
//public
public Thing(String param1,int paramm2) {
this(param1,param2,new Dependency1(),new Dependency2());
}
//package-private for the sake of testing
Thing(String param1,int param2,Dependency1 param3,Dependency2 param4) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = param3;
this.memberVar4 = param4;
}
//...rest of class...
}
在我看来,这是错误的,因为您正在编写代码来测试它而不是编写正确的代码.我想其他两个选项(我能想到的)是创建工厂或使用PowerMockito在适用的情况下注入新对象.就个人而言,我会写如下所示.
public class Thing {
//public
public Thing(String param1,int paramm2) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = new Dependency1();
this.memberVar4 = new Dependency2();
}
//...rest of class...
}
最佳答案
在任何已发布的内容中包含特定于测试的代码通常是不好的形式(但有例外情况,所以不要过于仔细地阅读).这有几个原因.
原文链接:https://www.f2er.com/java/437355.html1.外部人员可能会以一种你从未想过的方式使用测试构造函数,因为他们要么没有读取指示它用于测试的文档,要么开发人员忘记记录它.
假设您想要写一些有用的Thing扩展,但是您在Thing的公共/受保护API中找不到任何您想要它的东西.然后你会发现这个包私有构造函数似乎允许你想要的东西,但后来才发现它破坏了你的代码.你仍然无法做你想做的事情,你浪费时间探索没有成功的部分API.执行此操作的任何人都将对API持否定意见,并且不太可能将其推荐给其他任何人.
由于Java默认可见性的工作方式,此测试代码对生产代码中发生的重构不具有很强的适应性.如果测试代码位于同一个包中,则它只能调用该构造函数.如果重命名包,则调用它的测试代码将无法访问它,从而导致编译错误.当然,对于开发代码和测试的人来说,这是一个简单的解决方案,但即使没有添加这个小麻烦,重构也已经不好玩了.如果一群人以前能够成功地使用包私有的东西来满足他们的需求,那么它就成了一个主要问题 – 现在他们所有的代码都被打破了.
绝对存在难以编写代码的情况,这些代码可以在测试和生产环境中运行(例如,仅在应用程序联网时运行的功能).在这些情况下,依赖注入可能是你的朋友,但更简单的测试总是最好的,如果可以避免更复杂的测试方案而不牺牲功能覆盖或在API中添加钩子,你从未打算让其他开发人员看到.