实现受保护的无参数构造函数以进行单元测试
如果我有一个带有大旧(很多参数)构造函数的类型,那么为了创建一个派生的“假”类型以用于单元测试中的存根,实现受保护的无参数构造函数是否是一种有效的方法?
另一种方法是提取接口,但这在您无法完全控制的代码库中并不总是可取的......
If I have a type with a big-old (lots of params) constructor, is it a valid approach to implement a protected parameterless constructor simply for the purposes of creating a derived "Fake" type to use for stubbing in unit tests?
The alternative is to extract an interface, but this is not always desireable in a codebase you do not have full control over...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这并不理想,但它是有效的。
引用一些比我更了解这一点的人的话,在 单元测试的艺术 中,Roy Osherove 谈到单元测试就像代码的用户,因此专门为他们提供访问权限不一定是坏事。
在有效使用旧代码中, Michael Feathers 讨论了几种这样的技术,指出保护事物以供测试可能比公开它们更好,尽管这不一定是最好的做事方式。 (事实上,如果您正在使用遗留代码,我建议您阅读这本书,因为听起来您就是这样)。
我认为这取决于它是什么类型的代码 - 如果它是一个公共 API,人们可能会采取受保护的访问来意味着它被设计为被覆盖,这可能是一个坏主意,但在典型的商业应用程序上,这显然不是意味着被覆盖,我不认为这是一个问题。在这种情况下我有时确实会这样做。
It's not ideal, but it is valid.
To quote a couple of people who know more about this than me, in The Art of Unit Testing, Roy Osherove talks about unit tests being like a user of the code, and as such providing access specifically for them is not necessarily a bad thing.
And in Working Effectively with Legacy Code, Michael Feathers discusses several such techniques, pointing out that making things protected for testing can be better than making them public, although it's not necessarily the best way to do things. (In fact I'd recommend you read that book if you are working with legacy code, as it sounds like you are).
I think it depends what sort of code it is - if it's a public API where people are likely to take protected access to mean it's designed to be overridden, it's probably a bad idea, but on a typical business app where it's pretty obviously not meant to be overridden, I don't think it's a problem. I certainly do it sometimes in this situation.
由于您本质上必须将 protected 视为与 public 相同,因此从严格面向对象的角度来看,答案是否定的。
如果不是太麻烦的话,您可以添加一个私有无参数构造函数并通过反射调用它。
Since you essentially have to treat protected the same as public, the answer would be no from a strictly object-oriented point of view.
You could add a private parameterless constructor though and invoke it through reflection, if that's not too much hassle.
您不能创建一个扩展您要测试的类的类吗?这使您可以使用自己的构造函数,而无需创建接口。
修改代码或 API 来促进单元测试通常是不可取的(请参阅“我应该对私有方法进行单元测试”辩论),因此实际上使用新类而不是修改现有类可能是前进的方向。
Could you not create a class which extends the class you want to test? That lets you use your own constructor without having to create an interface.
Modifying your code or API to facilitate unit testing is generally undesirable (see the "Should I unit test private methods" debate), so actually using a new class rather than modifying your existing one might be the way forward.
有人认为,非密封类型应该始终声明受保护的无参数构造函数(其中其他类型有参数)。
这允许子类灵活地以自己的方式实例化该类,而不是被迫向基本构造函数提供参数。
模拟框架就是这样一个子类的例子,它希望能够自由地以自己的方式实例化该类;模拟对象不关心设置属性默认值或依赖项,因为它无论如何都会模拟返回值。
有一天,您自己的班级或图书馆客户可能对设置班级有截然不同的想法,并且您不想要一种几个月后无法发展的类型,因为您被迫将不再需要的东西推入班级基础演员。
在极少数情况下,您绝对需要强制某些初始化值,但这种情况很少见 - 请注意,结构不应具有无参数构造函数。
There is the argument that non-sealed types should always declare a protected parameterless constructor (where your others have parameters).
This allows flexibility for subclasses to instantiate the class in their own way, not forced to provide parameters to the base constructor.
Mocking frameworks are just such an example of a subclass that wants the freedom to be able to instantiate the class in its own way; the mock object doesn't care for setting property defaults or dependencies since it will mock the return values anyway.
One day, your own classes or library customers may have wildly different ideas about setting up the class, and you don't want a type that you cannot evolve months down the line because you're forced to push something that's no longer necessary into the base ctor.
There are rare cases when you absolutely need to force some initialization value, but it is rare - note that structs should not have parameterless ctors.