如何对对话框交互进行单元测试

Ras*_*sen 2 c# nunit unit-testing dialog

我有以下课程:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我将如何验证它返回正确的数据?例如。string.Empty还是在对话框中选择的内容取决于用户单击的内容?

我正在使用NUnit作为测试框架。

Mat*_*dge 6

一种选择是将不可测试的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;
}
Run Code Online (Sandbox Code Playgroud)

因此,您只需测试第二种方法即可,这很容易。


另一种选择是使用UI组件的模拟/伪造。但是,由于FolderBrowserDialog密封的,因此更加困难。

您可以做这样的事情,但这可能太过分了

首先,仅为要使用的部件定义一个接口:

public interface IFolderBrowserDialogWrapper
{
    DialogResult ShowDialog();
    string SelectedPath { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后将实数包装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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并创建一个伪造的版本进行测试,该版本仅返回传递给其构造函数的值:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您的方法可以将a 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;
}
Run Code Online (Sandbox Code Playgroud)

测试可以使用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));
}
Run Code Online (Sandbox Code Playgroud)

但这可能是无用的,除非您也在FolderBrowserDialog代码的其他地方创建了许多。