创建单元测试以确保不变性
我设计了一个 不可变类,因为我想为其提供值语义。我在类的注释部分写了一个提示
//“这个类是不可变的,向它添加新功能时不要更改它。”
但我知道,有时这些注释会被其他类忽略团队成员,所以我想创建一个单元测试作为额外的保障。知道如何实现这一点吗?可以通过反射检查类以确保只有构造函数更改其内部状态吗?
(使用 C# 2.0 和 NUnit,如果这对任何人都很重要的话)。
I have designed an immutable class, because I want to have value-semantics for it. I wrote a hint into the commentary section of the class
// "This class is immutable, don't change this when adding new features to it."
But I know, sometimes those commentaries are overlooked by other team members, so I would like to create a unit test as an additional safeguard. Any idea how to accomplish this? Can one inspect a class via reflection to make sure only the constructors change it's inner state?
(Using C# 2.0 and NUnit, if that's important for anyone).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一个支持我关于如何递归使用 FieldInfo.IsInitOnly 来测试不变性的评论的示例。
可能还有更多特殊情况需要考虑,例如我如何处理
string
,但我相信它只会给出假阴性,即会告诉您某些东西是可变的,但不是,而不是相反。逻辑是,每个字段都必须是只读的并且本身是不可变类型。请注意,它不会处理自引用类型或循环引用。
An example to back up my comment on how you can use
FieldInfo.IsInitOnly
recursively to test for immutability.There may be more special cases to consider like how I have handled
string
, but it will only give false negatives I believe, i.e. will tell you something is mutable that is not, not the other way around.The logic is, every field must be
readonly
and be an immutable type itself. Note that it will not cope with self referential types or circular references.您可以检查该类是否已密封,并使用反射检查每个字段是否为只读(使用
FieldInfo.IsInitOnly
)。当然,这只能确保浅不变性 - 它不会阻止某人将
List
字段放入其中,然后更改列表的内容。You could check that the class is sealed, and using reflection check that each field is read-only (using
FieldInfo.IsInitOnly
).Of course, that only ensures shallow immutability - it wouldn't stop someone from putting a
List<int>
field in there, and then changing the contents of the list.不确定您是否听说过 NDepend,但此工具允许您“内省”源代码并编译程序集并执行各种魔法,包括依赖项检查等等。
其中一项检查是对不变性的检查。例如,我有一个 IImmutable 标记接口,如果任何类型具有此接口但可变,则使用以下查询,NDepend 会导致我的构建失败:
您还可以将其配置为生成违规报告,以及失败的构建。
显然这实际上不是单元测试。但是,它可以集成为构建的一部分,并且像单元测试一样使构建失败,所以我想我会提到它!
请参阅此处,了解有关其实际功能和操作方式的更多信息。
Not sure if you've heard of NDepend, but this tool allows you to "introspect" over your source code and compiled assemblies and do all sorts of magic including dependency checking and much more.
One such check is a check for immutability. For instance, I have an
IImmutable
marker interface, and NDepend fails my build if any types have this interface but are mutable, using the following query:You can also configure it to generate violation reports, as well as failing builds.
Obviously this isn't actually a unit test. However, it can be integrated as part of your build, and fail your build just as a unit test would, so I thought I'd mention it!
See here for more info on what it actually does and how.