4

如果我有一个带有旧(很多参数)构造函数的类型,那么实现受保护的无参数构造函数是否是一种有效的方法,只是为了创建派生的“假”类型以用于单元测试中的存根?

另一种方法是提取接口,但这在您无法完全控制的代码库中并不总是可取的......

4

4 回答 4

2

由于您本质上必须将受保护与公共视为相同,因此从严格面向对象的角度来看,答案是否定的。

你可以添加一个私有的无参数构造函数并通过反射调用它,如果这不是太麻烦的话。

于 2010-10-20T13:31:36.983 回答
2

这并不理想,但它是有效的。

引用几个比我了解更多的人的话,在《单元测试的艺术》中,Roy Osherove 谈到单元测试就像是代码的用户,因此专门为他们提供访问权限并不一定是坏事。

《有效地处理遗留代码》中,Michael Feathers 讨论了几种这样的技术,指出将事物保护以供测试可能比将它们公开更好,尽管这不一定是做事的最佳方式。(事实上​​,如果您正在使用遗留代码,我建议您阅读那本书,因为听起来像您)。

我认为这取决于它是什么类型的代码 - 如果它是一个公共 API,人们可能会采取受保护的访问来表示它被设计为被覆盖,这可能是一个坏主意,但在一个典型的商业应用程序上,这显然不是意味着被覆盖,我认为这不是问题。在这种情况下,我当然有时会这样做。

于 2010-10-20T13:47:57.940 回答
1

您不能创建一个扩展您要测试的类的类吗?这使您可以使用自己的构造函数而无需创建接口。

修改代码或 API 以促进单元测试通常是不可取的(请参阅“我应该对私有方法进行单元测试”辩论),因此实际使用新类而不是修改现有类可能是前进的方向。

于 2010-10-20T13:33:10.600 回答
0

有一个论点是非密封类型应该总是声明一个受保护的无参数构造函数(你的其他类型有参数)。

这允许子类以自己的方式灵活地实例化类,而不是被迫向基构造函数提供参数。

模拟框架就是这样一个子类的例子,它希望能够以自己的方式实例化类。模拟对象不关心设置属性默认值或依赖项,因为它无论如何都会模拟返回值。

有一天,您自己的课程或图书馆客户可能对设置课程有截然不同的想法,并且您不想要一种无法在几个月后发展的类型,因为您被迫将不再需要的东西推入基础 ctor。

在极少数情况下,您绝对需要强制执行某些初始化值,但这种情况很少见 - 请注意,结构不应具有无参数的 ctor。

于 2011-05-20T16:15:48.367 回答