消息框和单元测试
本文关键字:单元测试 消息 | 更新日期: 2023-09-27 18:18:21
我正在尝试找到将消息框与我的逻辑分离的最佳方法,以便我可以正确地对其进行单元测试。现在我想知道如果我只创建一个单独的帮助程序类 (C#( 是否足够,我可以稍后为我的消息框存根。例如:
static class messageBoxHelper
{
public static void msgBoxAlg(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icons, bool show)
{
if (show)
{
MessageBox.Show(message, title, buttons, icons);
}
}
然后每次我需要使用消息框时,我只会使用 messageboxHelper/msgBoxAlg(...( 而不是 messagebox.show(...(。使用布尔显示,我可以在测试期间启用或禁用它。
我只是想知道这是否是"正确的方式"。我的意思是,有没有更简单或更好的方法来正确执行此操作?我不能只是放弃消息框,它们将"重要"信息传递给用户("你想关闭这个窗口吗?是/否等(。也可能只是我没有使用适当的软件工程,我应该更多地将我的消息框与我的业务逻辑分离?
是的,这是正确的方式。但是,您应该实现IDialogService
并将其注入应显示对话框的类中,而不是静态类:
public interface IDialogService
{
void ShowMessageBox(...);
...
}
public class SomeClass
{
private IDialogService dialogService;
public SomeClass(IDialogService dialogService)
{
this.dialogService = dialogService;
}
public void SomeLogic()
{
...
if (ok)
{
this.dialogService.ShowMessageBox("SUCCESS", ...);
}
else
{
this.dialogService.ShowMessageBox("SHIT HAPPENS...", ...);
}
}
}
在测试SomeClass
期间,您应该注入IDialogService
的模拟对象而不是真实对象。
如果需要测试更多 UI 逻辑,请考虑使用 MVVM 模式。
查看控制反转 (IoC(,基本原则是执行操作等的东西应作为接口传入,然后使用 IoC 容器将接口绑定到应用的特定实现。为了在您的情况下轻松实现这一点,请将消息框作为接口传递,并在单元测试中创建该消息框服务的模拟(假(版本,该服务不显示消息框
查看 http://martinfowler.com/articles/injection.html 以获取有关 IoC 的详细信息,我最喜欢的容器是 Ninject(http://ninject.org(
理想情况下,您希望使用单元测试测试的代码是逻辑代码,而不是 UI。因此,测试的逻辑不应真正显示消息框。如果你想测试 UI,那么我建议编码的 UI 测试。
从你的问题来看,我想你的代码不应该真的使用MessageBox
。也许可以考虑使用回调或任意Action
,或者卢克·麦格雷戈和谢尔盖五世提到的方法。
单元测试",就其确切含义而言,是对原子行为的测试。这不是您可以为代码进行的唯一一种代码驱动测试。特别是对于使用您提到的"是/否"对话框测试较长的方案,更大规模的代码驱动测试通常比单元测试更有效。
但是,为了能够更轻松地编写它们,最好不仅像Sergii提到的那样创建一个特殊服务,而且还要使其调用异步:
public interface IDialogService
{
Task<bool> ShowYesNoMessageBox(...);
...
}
通过将消息框包装在非异步服务调用中并模拟它们,对于较长的场景,您将开始与"排列-操作-断言"模式相矛盾,方法是在用户操作实际发生之前预测用户操作(执行"安排"而不是"操作"(,这可能会在测试中引起许多问题,尤其是在使用 BDD/SpecFlow 完成测试时。使这些调用异步可以避免此类问题。请参阅我的博客文章,了解使用消息框进行更大规模测试的详细信息和示例。