我是单元测试的新手,在这里遇到了一个简单的用例。我有声明为私有的setter(除了Spring之外,不希望任何人设置这些变量)
private setX(T x) {
this.x = x;
}
在编写单元测试时,当我想为这些变量设置值时,我不能。一个快速的解决办法是设置公共设置器,但这看起来不太好。我使用Mockito作为mocking框架,使用Junit进行单元测试。
感谢所有的帮助。
编辑:
Class A {
private Clazz clazz;
//to be used only by spring
private setClazz(Clazz clazz) {
this.clazz = clazz;
}
使它们受到保护或包私有,并将测试放在与类相同的包中正在测试中。
或者像Spring那样使用反射来调用setter。
或者使用Mockito的InjectMocks
注释,它将通过使用反射调用setter来注入mock依赖项。
不要直接单元测试私有成员。
(互联网上对此有很多争论。)
单元测试不一定测试代码中的属性和方法,而是测试代码的功能。特别是对象公开的面向外部的业务功能。因此,当你面对一个需要测试的私人会员时,有两件事是正确的:
- 业务功能可以根据状态调用该私有功能。因此,如果当前的单元测试没有将该功能作为代码覆盖范围的一部分来调用,那么这些测试就不是详尽无遗的,并且存在未被测试的状态。创建一个测试,在调用面向公共的功能之前安排该状态,以便间接测试该私有成员
- 测试是详尽无遗的,业务功能在任何已知条件下都不会实际调用该私有成员。在这种情况下,可以简单地从代码中删除该私有成员
面向对象设计的原则适用于单元测试,就像它们适用于任何其他代码一样。封装仍然是封装。如果单元测试强行破坏封装,那么它们很快就会与被测试的代码紧密耦合,这会使它们变得更加脆弱。
考虑红/绿/重构周期中的"重构"步骤。如果测试与被测试组件的私有内部紧密耦合,那么重构该组件将需要更改测试。不仅重构这些测试,而且更改他们正在测试的逻辑。这打破了TDD循环。
将其扩展到更大的代码系统中,测试将成为重构该代码的障碍,而它们本应是重构该代码的资产。如果测试只验证所产生的面向外部的功能,那么可以很容易地重构代码的内部,并使用测试来验证重构工作。