消息框和单元测试

问题描述 投票:8回答:4

我正在尝试找到从我的逻辑中解开消息框的最佳方法,以便我可以正确地对其进行单元测试。现在我想知道如果我只是创建了一个单独的帮助类(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(...)。使用bool show我可以在测试期间启用或禁用它。

我只是想知道这是否是“正确的方法”。我的意思是,是否有更简单或更好的方法来做到这一点?我不能只丢弃消息框,他们将“重要”信息传递给用户(“你想关闭这个窗口吗?”是/否等)。它也可能只是我没有使用适当的软件工程,我应该将我的消息框与我的bussinesslogic分开更多?

c# unit-testing messagebox
4个回答
31
投票

是的,这是正确的方式。但是,您应该实现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模式。


2
投票

查看控制反转(IoC),基本原则是执行操作的事物应该作为接口传递,然后使用IoC容器将接口绑定到应用程序的特定实现。为了在您的情况下轻松实现这一点,将作为接口的消息框的内容传递给您的单元测试创​​建该消息框服务的模拟(假)版本,该服务不显示消息框

看看http://martinfowler.com/articles/injection.html有关IoC的详细信息,我最喜欢的容器是Ninject(http://ninject.org)


1
投票

理想情况下,您希望使用单元测试进行测试的代码是逻辑而不是UI。因此,您的测试逻辑不应该真正显示消息框。如果你想测试用户界面,那么我会建议Coded UI Tests

从您的问题来看,我认为您的代码不应该真正使用MessageBox。也许考虑使用回调或任意Action,或Luke McGregor和Sergey V.提到的方法。


1
投票

“单元测试”,其确切含义,是对原子行为的测试。这不是您可以为代码进行的唯一一种代码驱动的测试。特别是对于使用“是/否”对话框测试更长的场景,大规模代码驱动的测试通常比单元测试更有效。

但是为了能够更容易地编写它们,不仅可以创建Sergii提到的特殊服务,而且还可以使其调用异步:

public interface IDialogService
{
    Task<bool> ShowYesNoMessageBox(...);
    ...
}

通过在非异步服务调用中包装消息框并模拟它们,对于更长的情况,您将通过在实际发生之前预测用户操作(做“安排”而不是“行动”)开始与“安排 - 行动 - 断言”模式相矛盾,这可能会导致测试中出现许多问题,特别是如果您的测试是使用BDD / SpecFlow完成的。使这些调用异步可以避免这些问题。有关详细信息和使用消息框进行大规模测试的示例,请参阅我的blog article

© www.soinside.com 2019 - 2024. All rights reserved.