C# 使用和不使用私有访问器的单元测试

C# 使用和不使用私有访问器的单元测试,c#,unit-testing,C#,Unit Testing,使用私有访问器测试代码有什么缺点吗 我正在权衡使用私有访问器只测试GUI的选项,而不是公开的方法/属性 这将允许进行我需要的一些GUI测试,我只是想确保它们在使用私有访问器时不会有任何隐藏的“陷阱”。最好不要使用它们,而是尝试找出是否可以注入任何依赖项。除非您在处理遗留代码时希望使用私有访问器创建一些单元测试,否则我建议不要使用它们,即使在这种情况下,我也建议您在重构遗留代码之前暂时这样做 除了广告网所说的以外。 我只能在测试中使用这些私有属性,直到我完成重构(到模型视图控制器、模型视图演示器、

使用私有访问器测试代码有什么缺点吗

我正在权衡使用私有访问器只测试GUI的选项,而不是公开的方法/属性


这将允许进行我需要的一些GUI测试,我只是想确保它们在使用私有访问器时不会有任何隐藏的“陷阱”。

最好不要使用它们,而是尝试找出是否可以注入任何依赖项。除非您在处理遗留代码时希望使用私有访问器创建一些单元测试,否则我建议不要使用它们,即使在这种情况下,我也建议您在重构遗留代码之前暂时这样做

除了广告网所说的以外。
我只能在测试中使用这些私有属性,直到我完成重构(到模型视图控制器、模型视图演示器、模型视图视图模型),这样我就不必测试GUI了

总而言之,您声明的目标是:

我正在权衡使用私有访问器仅用于测试我的GUI的选项。。。这将允许一些我需要的GUI测试

简言之,是的,存在陷阱。您正在测试的代码仍然与用户界面紧密耦合

在评论中,您阐明了您的目标/问题:


如果我想进行测试,可以拖放。自定义控件,重写事件

我只能说欢迎你上船。近半个世纪以来,软件行业一直在与此作斗争。事实上,测试UI是非常困难的。是的,您可以使用一段与UI元素紧密耦合的代码,并尝试将其自动化;然而,你将全力以赴地反对糟糕的假设

可测试UI的“诀窍”不是使UI可测试,而是从UI中删除要测试的代码。因此,N层应用程序开发和表示设计模式(如MVC、MVVM等)被广泛接受

见下文:

许多设计模式背后的主要目标或驱动力是消除行为和表示之间的紧密耦合。这使您能够在没有用户界面的情况下测试拖放等行为。我的建议是检查模式,选择一个您喜欢的模式,然后在编写单元测试时开始重构代码

编写测试UI的另一种方法是从用户界面代码中删除每个if、else、for、while、switch或other。由此产生的UI“外壳”应该具有很强的变化弹性。在使用依赖于反射的数据绑定(这通常是一种可接受的做法)时要小心。这样做的主要缺点是编译器无法告诉您成员不再存在

已更新

@蒂米,你写道:

。。。例如,如果我想测试鼠标点击行为

那么,如果鼠标单击行为不能移动到控制器,而不是嵌入到表单中,该怎么办?我猜“Close”按钮可能有问题,但除此之外,为什么不将逻辑移到另一个可以测试的类

顺便说一句,你不必只选择一种模式MVC、MVVM等,它们是“指导原则”或“建议”,而不是硬性规定,所以不要觉得可笑。只需尝试将逻辑与UI分离并独立测试即可。例如,您的“单击”事件是否更适合简单的命令类?使用命令模式很简单,创建一个对象并执行它。考虑文件夹复制表单的示例代码:

private void OnCopyClick(object sender, EventArgs args)
{
    var cmd = new MyCopyCommand(this.FolderPath, this.txtTargetFolderPath.Text);
    new ErrorHandler(this).Perform(cmd);
}
这工作得很好,除了提供命令之外,它没有“真实”逻辑,也没有条件代码路径。请注意,我们甚至不直接调用命令,而是将其推迟到能够适当处理错误的人。通常,这个“ErrorHandler”会提供给表单,而不是直接构造,但您可以理解

因此,我们应该能够轻松地验证mycopy命令的正确行为。最后,您应该在UI中得到一堆“平面函数”,即没有嵌套或大括号的函数。当然,这是一条经验法则,不要走得太极端以至于妨碍你的工作效率


我知道这似乎是一个很大的工作,但说实话,这不是当你已经在写一套测试。您可以高效地编写可靠的代码。你只需要知道什么时候该作弊,什么时候不该作弊。这是有经验的,20年后,10个修女的写作,我还是偶尔会失败一次。如果由于未执行此操作而出现故障,请首先从UI中提取逻辑,然后编写单元测试以证明其故障,然后进行修复。

如果要测试,请拖放。自定义控件,重写事件?问题是我们的视图经常中断,视图下面的层无法捕捉错误。我试图构建一个测试类来覆盖这些情况。这取决于您的架构,在MVVM或MVP中,您可以触发事件并测试处理事件的代码,但它不会测试真实视图本身。所以,如果你想测试视图,你应该有UI测试。为什么它不测试真实的事件呢?如果可以触发事件,并且在事件发生后,所有视图数据都处于正确的状态。这不是一个UI测试吗?谢谢csharp,这很有帮助,还有一个问题。说它不可能重构我们所有的逻辑出我们的看法。我想通过UI测试来测试我们的用户故事。例如,给定窗口处于默认状态,当按下ButtonX时,文本变为绿色。我可以通过UI直接测试所有这些,你觉得有什么问题吗?或者它不是真的在测试UI吗?比如performClick()…或者如果我自己使用私有访问器和设置事件调用。