让我解释一下问题场景。我的任务是修改复杂的函数testFunc((,如下所示。
public String testFunc() {
String a = func1();
String b = func2(a);
String c = func3(b);
return c;
}
private String func1(){
return "hello";
}
private String func2(String p1){
return "a" + p1;
}
private String func3(String p1){
return "b" + p1;
}
我修改了testFunc方法并包含我的逻辑。但是作为一个优秀的开发人员,我希望为我编写的额外逻辑编写 untit 测试。 但我没有时间也没有耐心来测试整个方法。我只想测试我添加的逻辑。
public String testFunc() {
String a = func1();
String b = func2(a);
String c = func3(b);
String d = func4(c)
return d;
}
protected final String func4(String p1) {
return "1" + p1;
}
我是否有意义将方法func4 作为受保护的最终方法,以便我可以彻底对逻辑进行单元测试。还是糟糕的编码实践?
我会将其打包设为私有,这比受保护的限制性更强。如果您已经在项目中使用了 Guava,您甚至可以用@VisibleForTesting
注释该方法以明确您的意图:
@VisibleForTesting final String func4(String p1) {
//...
}
最后,包私有方法不会向外界公开,也不是 API 的一部分,因此它不会破坏封装。
这是一种不好的做法。私有/受保护的方法应该可以通过调用它们的公共方法进行测试。通过将访问修饰符更改为包私有,实质上是向其他类公开实现细节,从而减少封装。
如果事实证明这很难,您应该考虑重新设计公共 API。
更改单元测试方法的可见性不是一个好的做法。
如果你在项目中使用Spring,那么你可以使用ReflectionTestUtilsorg.springframework.test.util.ReflectionTestUtils
(反射简化(来访问私有方法和属性。
如果你不想使用Spring,那么你必须选择java反射。
好吧,我会开始问题中的两句话对我来说有些矛盾:
-
但是作为一个优秀的开发人员,我希望为我编写的额外逻辑编写单元测试。
和
-
但我没有时间和耐心来测试整个方法。我 希望只测试我添加的逻辑。
你要么是一个优秀的开发人员,自上而下地做事,要么没有耐心,然后没有什么能真正帮助你。
要回答您的问题,公开无法重用的私有方法是非常糟糕的做法,因此不是一个好方法。虽然您所做的更改不能遗漏您为其执行此更改的类的上下文,例如您有:
class MyClass {
public String testFunc() {
String a = func1();
String b = func2(a);
String c = func3(b);
return c;
}
private String func1(){
return "hello";
}
private String func2(String p1){
return "a" + p1;
}
private String func3(String p1){
return "b" + p1;
}
}
因此,有几种可能的方法可以使用新功能扩展此逻辑,例如,您想用一个新类装饰初始类并向其添加新函数,例如:
class MyNewClass extends MyClass{
private MyClass delegate;
public MyNewClass(MyClass delegate) {
this.delegate = delegate;
}
public String testFunc() {
String c = delegate.testFunc();
return func4(c);
}
private final String func4(String p1) {
return "1" + p1;
}
}
现在,您可以通过模拟实例并仅检查新添加MyClass
逻辑来编写单元测试。
另一种可能的替代方案是将新功能提取到自己的类中,并仅为它编写测试。