目前我需要写SecondClass
并决定使用这种解决方案进行编写,否则它将无法测试。
@Component
public class FirstClass {
public void doStuff() {
System.out.println("First Class stuff!");
}
}
@Component
public class SecondClass {
private final Random random;
private final FirstClass firstClass;
@Autowired
public SecondClass(FirstClass firstClass) {
this(new Random(), firstClass);
}
public SecondClass(Random random, FirstClass firstClass) {
this.random = random;
this.firstClass = firstClass;
}
public void doOtherStuff() {
firstClass.doStuff();
System.out.println("Second Class stuff " + random.nextInt(10));
}
}
我的同事们并不喜欢我解决问题的方法,并喜欢SecondClass
这样的实施:
@Component
public class SecondClass {
private Random random;
private final FirstClass firstClass;
@Autowired
public SecondClass(FirstClass firstClass) {
this.random = new Random();
this.firstClass = firstClass;
}
public void doOtherStuff() {
firstClass.doStuff();
System.out.println("Second Class stuff " + random.nextInt(10));
}
public void setRandom(Random random) {
this.random = random;
}
}
我不同意这种解决方案,因为我认为Random
是这个类的必要部分,它不会在运行时更改,并且setter仅用于测试目的和那个为什么我更喜欢两个构造函数的解决方案
我们也提出了这种构造函数:
@Autowired(required = false)
public SecondClass(FirstClasss firstClass, Random random) {
this.random = (random == null ? new Random() : random)
...
}
但实际上构造函数中注入了更多的组件,因此如果需要所有组件,那将更为可取。
我很感兴趣,如果有人在此之前有这种经历吗?您如何看待这种情况,以及是否有更好的方法来解决这个问题?
答案 0 :(得分:2)
你的问题源于最后的领域。跟随鲍勃叔叔,随意让他们受到保护,这样你就可以在测试课上给他们写信。您不是在编写界面,而是在编写代码,因此访问修饰符并不重要,因为它允许包访问,所以受保护很好。
或者您可以通过硬连接将它们自己设置在测试用例中,比如ReflectionUtils.setField
答案 1 :(得分:1)
如果在SecondClass
中声明了两个构造函数,并且仅在单元测试中使用其中一个,则意味着单元测试的构造函数可以替换为单元测试的更相关技巧,例如用于设置random
字段值的反射
如果可以避免,则不应仅为单元测试打开API
当您无法选择时,您应该打开您的API以进行单元测试。
如果random
字段是只读的,并且只要SecondClass
被实例化,就会知道一个已知值,那么SecondClass
应该有一个构造函数。 random
字段应该是最终的,并在SecondClass
的构造函数中进行评估。
答案 2 :(得分:1)
你是对的,我的朋友。您的方法是正确的,因为根据面向对象的设计,必须在执行任何构造函数后将对象初始化为有效状态。因此,如果random
字段是必需的,必须在所有构造函数中初始化。此外,如果以后不再更改,必须是最终(并且没有设置者)。所以第二种解决方案不正确,因为它违反了这一原则。
我不喜欢第三种解决方案,因为它对客户端代码来说可能是愚蠢的:虽然客户端假设null
被设置为输入值,但实际上另一个(未受控制的)值是反而用了。
因此,如果您需要SecondClass
的构造函数可以测试,请转到并添加它。因为如果一个类不可测试,它也不可执行。测试是确保类可以使用的正确方法。