启用方法的单元测试,使其受到保护
Enable unit testing of a method my making it protected
让我解释一下问题场景。我的任务是修改如下所示的复杂函数 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 方法并包含了我的逻辑。但作为一名优秀的开发人员,我希望为我编写的额外逻辑编写单元测试。
但是我没有时间也没有耐心去测试整个方法。我只想测试我添加的逻辑。
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 设置为 protected final 对我来说是否有意义,以便我可以对逻辑进行彻底的单元测试。还是编码习惯不好?
我会把它打包成私有的,这比保护更严格。如果您已经在您的项目中使用 Guava,您甚至可以使用 @VisibleForTesting
注释该方法以明确您的意图:
@VisibleForTesting final String func4(String p1) {
//...
}
归根结底,一个包的私有方法没有暴露给外界,也不是你的API的一部分,所以它不会破坏封装。
更改单元测试方法的可见性不是一个好的做法。
如果您在项目中使用 Spring,则可以使用 ReflectionTestUtilsorg.springframework.test.util.ReflectionTestUtils
(反射简化)来访问私有方法和属性。
如果您不想使用 Spring,那么您必须进行 java 反射。
这是一种不好的做法。 Private/protected 方法应该可以通过调用它们的 public 方法进行测试。通过将访问修饰符更改为 package-private,您实质上是将实现细节公开给其他 类,从而减少了封装。
如果这很难,您应该考虑重新设计 public API。
好吧,我要开始说问题中的两句话对我来说有点矛盾:
But being a good developer, I wish to write unit tests for the extra logic i have written.
和
But i do not have time nor the patience to test the entire method. I
wish to test only the logic i have added.
你要么是一个优秀的开发人员并且自上而下地做事,要么没有耐心,那么没有什么能真正帮助你。
为了回答你的问题,公开不能重复使用的私有方法是非常糟糕的做法,因此不是一个好的方法。虽然您所做的更改不能脱离 class 的上下文,但您进行此更改的原因是:
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;
}
}
因此,您可以通过几种可能的方式使用新功能扩展此逻辑,例如,您想要 decorate 初始 class 一个新功能并将新功能添加到它,例如:
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;
}
}
现在您可以通过 mocking MyClass
实例编写单元测试并仅检查新添加的逻辑。
另一种可能的替代方法是将新功能提取到它自己的 class 中,并仅为它编写测试。
让我解释一下问题场景。我的任务是修改如下所示的复杂函数 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 方法并包含了我的逻辑。但作为一名优秀的开发人员,我希望为我编写的额外逻辑编写单元测试。 但是我没有时间也没有耐心去测试整个方法。我只想测试我添加的逻辑。
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 设置为 protected final 对我来说是否有意义,以便我可以对逻辑进行彻底的单元测试。还是编码习惯不好?
我会把它打包成私有的,这比保护更严格。如果您已经在您的项目中使用 Guava,您甚至可以使用 @VisibleForTesting
注释该方法以明确您的意图:
@VisibleForTesting final String func4(String p1) {
//...
}
归根结底,一个包的私有方法没有暴露给外界,也不是你的API的一部分,所以它不会破坏封装。
更改单元测试方法的可见性不是一个好的做法。
如果您在项目中使用 Spring,则可以使用 ReflectionTestUtilsorg.springframework.test.util.ReflectionTestUtils
(反射简化)来访问私有方法和属性。
如果您不想使用 Spring,那么您必须进行 java 反射。
这是一种不好的做法。 Private/protected 方法应该可以通过调用它们的 public 方法进行测试。通过将访问修饰符更改为 package-private,您实质上是将实现细节公开给其他 类,从而减少了封装。
如果这很难,您应该考虑重新设计 public API。
好吧,我要开始说问题中的两句话对我来说有点矛盾:
But being a good developer, I wish to write unit tests for the extra logic i have written.
和
But i do not have time nor the patience to test the entire method. I wish to test only the logic i have added.
你要么是一个优秀的开发人员并且自上而下地做事,要么没有耐心,那么没有什么能真正帮助你。
为了回答你的问题,公开不能重复使用的私有方法是非常糟糕的做法,因此不是一个好的方法。虽然您所做的更改不能脱离 class 的上下文,但您进行此更改的原因是:
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;
}
}
因此,您可以通过几种可能的方式使用新功能扩展此逻辑,例如,您想要 decorate 初始 class 一个新功能并将新功能添加到它,例如:
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;
}
}
现在您可以通过 mocking MyClass
实例编写单元测试并仅检查新添加的逻辑。
另一种可能的替代方法是将新功能提取到它自己的 class 中,并仅为它编写测试。