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

时间:2012-12-07 20:42:09

标签: c# unit-testing

使用私有访问器测试一段代码是否有任何缺点?

我正在权衡使用私有访问器来测试我的GUI,而不是公开暴露的方法/属性。

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

3 个答案:

答案 0 :(得分:1)

最好不要使用它们,而是试着找出是否可以注入任何依赖。除非您正在使用私有访问器创建一些单元测试的遗留代码,否则我建议不要使用它们,即使在这种情况下,我建议您暂时执行此操作,直到您重构遗留代码为止。

答案 1 :(得分:1)

所以回顾一下,你的既定目标是:

  
    

我正在权衡使用私有访问器来测试我的GUI ...这将允许我需要的一些GUI测试......

  

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

在评论中,您将目标/问题澄清为:

  
    

如果我想测试,拖放的情况怎么样?自定义控件,Overriden事件?

  

我只能说欢迎乘坐。近半个世纪以来,软件行业一直在努力解决这个问题。事实仍然是测试UI很难,真的很难。是的,您可以使用与UI元素紧密耦合的一段代码并尝试自动化它;然而,你会在与糟糕的假设相抗衡的情况下进行斗争。

可测试UI的“技巧”不是让你的UI可测试,而是从UI中删除你想要测试的代码。因此广泛接受N-Tier应用程序开发和表示设计模式,如MVC,MVVM等。

请参阅以下内容:

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

考虑编写用于测试的UI的另一种方法是从用户界面代码中删除if,else,for,while,switch或其他control statement。由此产生的UI的'shell'应该非常适应变化。使用依赖于反射的数据绑定之类的东西时要小心(这通常是可接受的做法)。这样做的主要缺点是编译器无法告诉您成员不再存在。

<强>更新

@timmy你写道:

  
    

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

  

那么鼠标单击行为又不能移动到控制器而不是嵌入到表单中呢?我想“关闭”按钮可能有问题,但除此之外为什么不将逻辑移动到另一个可以进行测试的类?

顺便说一句,你不必只挑选一种模式MVC,MVVM等,它们是“指导方针”或“建议”而不是硬规则,所以不要用它来搞笑。只需尝试将逻辑与UI分开并独立测试。举个例子,也许你的“Click”事件更适合一个简单的命令类?使用命令模式很容易,新建一个对象并执行它。请考虑文件夹副本表单的示例代码:

private void OnCopyClick(object sender, EventArgs args)
{
    var cmd = new MyCopyCommand(this.FolderPath, this.txtTargetFolderPath.Text);
    new ErrorHandler(this).Perform(cmd);
}

这很好用,它除了提供命令之外没有“真正的”逻辑,并且没有条件代码路径。请注意,我们甚至不直接调用命令,而是将其推迟给能够正确处理错误的人。通常这个'ErrorHandler'将提供给Form而不是直接构造,但你明白了。

由此我们应该能够轻松验证MyCopyCommand的正确行为。最后,您应该在UI中使用一堆“平面函数”,即。没有嵌套或花括号的函数。当然,这是一个经验法则,不要被视为极端,以防止你的生产力。

我知道这可能看起来很多工作,但事实上,当你已经在编写一组测试时,并不是这样。您可以高效地 AND 编写可靠的代码。你只需要知道什么时候作弊,什么时候不作弊。这有经验,20年后,有10个人写NUnits,我偶尔也会失败。当因为你没有这样做而出现问题时,首先从UI中提取逻辑,然后编写一个单元测试来证明它被破坏,然后修复它。

答案 2 :(得分:0)

除了AD.NET所说的。 我只能在测试中使用这些私有属性,直到我完成重构(模型视图控制器,模型视图展示器,模型视图ViewModel),这样我就不必测试GUI了!