c# - 如何对对话交互进行单元测试

标签 c# unit-testing dialog nunit

我有以下类(class):

public class DirectoryFinder : IDirectoryFinder
{
    public string GetDirectory(string whereTo)
    {
        FolderBrowserDialog dialog = new FolderBrowserDialog {Description = whereTo};
        DialogResult result = dialog.ShowDialog();
        return result == DialogResult.OK ? dialog.SelectedPath : string.Empty;
    }
}

我将如何验证它是否返回了正确的数据? 例如。 string.Empty 或根据用户点击的内容在对话框中选择的任何内容?

我使用 NUnit 作为测试框架。

最佳答案

一个选择是将不可测试的 UI 部分从可测试的业务逻辑中分离出来:

public string GetDirectory(string whereTo)
{
    FolderBrowserDialog dialog = new FolderBrowserDialog { Description = whereTo };
    DialogResult result = dialog.ShowDialog();

    return GetDirectory(dialog.SelectedPath, result);
}

public string GetDirectory(string selectedPath, DialogResult result)
{
    return result == DialogResult.OK ? selectedPath : string.Empty;
}

所以你只需要测试第二种方法,这变得很容易。


另一种选择是使用 UI 组件的模拟/伪造。但是,FolderBrowserDialog密封的,这使得这更难。

你可以做这样的事情,但这可能有点矫枉过正

首先,为您要使用的部分定义一个接口(interface):

public interface IFolderBrowserDialogWrapper
{
    DialogResult ShowDialog();
    string SelectedPath { get; }
}

然后将真正的 FolderBrowserDialog 包装在您的新界面中:

public class FolderBrowserDialogWrapper : IFolderBrowserDialogWrapper
{
    private readonly FolderBrowserDialog m_dialog;

    public DialogResult ShowDialog()
    {
        return m_dialog.ShowDialog();
    }

    public string SelectedPath
    {
        get { return m_dialog.SelectedPath; }
    }

    public FolderBrowserDialogWrapper(FolderBrowserDialog dialog)
    {
        m_dialog = dialog;
    }
}

并创建一个用于测试的假版本,它只返回传递给其构造函数的值:

public class FakeFolderBrowserDialogWrapper : IFolderBrowserDialogWrapper
{
    private readonly DialogResult m_result;
    private readonly string m_selectedPath;

    public DialogResult ShowDialog()
    {
        return m_result;
    }

    public string SelectedPath
    {
        get { return m_selectedPath; }
    }

    public FakeFolderBrowserDialogWrapper(string selectedPath, DialogResult result)
    {
        m_selectedPath = selectedPath;
        m_result = result;
    }
}

然后您的方法可以使用 FolderBrowserDialogWrapper 进行真正的对话:

public string GetDirectory(string whereTo)
{
    var f = new FolderBrowserDialogWrapper(
        new FolderBrowserDialog { Description = whereTo });
    return GetDirectory(f);
}

public string GetDirectory(IFolderBrowserDialogWrapper dialog)
{
    DialogResult result = dialog.ShowDialog();
    return result == DialogResult.OK ? dialog.SelectedPath : string.Empty;
}

并且测试可以使用 FakeFolderBrowserDialogWrapper 来绕过 UI:

[Test]
public static void TestDirectoryFinderGetDirectoryWithOKExpectThePath()
{
    const string expectedPath = @"C:\temp";

    var dlg = new FakeFolderBrowserDialogWrapper(expectedPath, DialogResult.OK);

    var df = new DirectoryFinder();
    string result = df.GetDirectory(dlg);

    Assert.That(result, Is.EqualTo(expectedPath));
}

[Test]
public static void TestDirectoryFinderGetDirectoryWithCancelExpectEmptyString()
{
    const string expectedPath = @"C:\temp";

    var dlg = new FakeFolderBrowserDialogWrapper(expectedPath, DialogResult.Cancel);

    var df = new DirectoryFinder();
    string result = df.GetDirectory(dlg);

    Assert.That(result, Is.EqualTo(string.Empty));
}

但这可能有点夸张,除非您也在代码的其他地方创建大量的 FolderBrowserDialog

关于c# - 如何对对话交互进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31100492/

相关文章:

c# - 无论如何在控制台程序中获取图形对象?

c# - Entity Framework 外键跟踪导致问题

C# 编码问题

java - Spring:模拟 beans 的正确方法

javascript - 如何将局部变量声明为全局变量

安卓进度对话框

Jquery 对话框新按钮

c# - MYSQL SQL语法错误c#

unit-testing - 使用 fakeAsync 进行 Angular2 测试

java - Maven 从包中运行所有测试