【问题标题】:How to write unit test for method in back of windows form code如何在windows表单代码后面为方法编写单元测试
【发布时间】:2018-06-05 04:14:28
【问题描述】:

我有要测试的方法,但我收到此错误“在创建窗口句柄之前无法在控件上调用 Invoke 或 BeginInvoke。”现在我还有一个列表框,正在我正在测试的那个函数中填充。因此,当我将方法分离到另一个类时,这是一个问题。

我理解这一点,因为表单需要先运行,但还有其他选择吗?

public partial class ImportForm : Form
{
    public ImportForm()
    {
    }
    public bool Test(string[] fileNames)//Method to test
    {
        foreach (DataTable table in result.Tables)
        {
            foreach (DataRow dr in table.Rows)
            {
                if (!db.CouncilRefundCases.Any(
                        c => c.RequestReference == dr.ItemArray[1].ToString()))
                {
                    CouncilRefundCase data = new CouncilRefundCase()
                    {
                        FileId = fileId,
                        RequestReference = Convert.ToString(dr.ItemArray[1]),
                        CancelReason = Convert.ToString(dr.ItemArray[2]),
                        ProcessStatusId = (int?)ProcessStatus.Unprocessed,
                        ProcessDescription = new EnumHelper().GetDescription(ProcessStatus.Unprocessed),
                        DateCaptured = DateTime.Now
                    };

                    db.CouncilRefundCases.InsertOnSubmit(data);

                    //Succeeded ones
                    var item = new ListViewItem(dr.ItemArray[1].ToString());
                    lstSuccessSummary.Invoke((Action)delegate
                    {
                        lstSuccessSummary.Items.Add(item);
                    });
                }
                else
                {
                    //Failed ones
                    var item = new ListViewItem(dr.ItemArray[1].ToString());
                    lstSummary.Invoke((Action)delegate
                    {
                        lstSummary.Items.Add(item);
                    });
                }
            }
        }
        return true;
    }
}

这是我的单元测试

[TestMethod]
public void TestTest()
{
    bool results=false;
    var files = new string[4];
    files[0] = @"filename1.xlsx";
    files[1] = @"filename2.xlsx";

    ImportForm form= new ImportForm();
     results = form.Test(files);

    Assert.AreEqual(true, results);
}

【问题讨论】:

标签: c# .net winforms unit-testing mstest


【解决方案1】:

注意 - 阅读答案之前

一般来说,UI代码和业务逻辑紧密耦合并不是一个好主意,但是如果你遇到无法重构与UI解耦的代码,你可以使用下面的解决方案来解决问题。

问题和解决方案

在显示窗体之前,窗体及其控件不处于Created 状态,不能使用窗体或其控件的Invoke 方法。

要解决此问题,您可以强制创建表单及其控件。为此,只需调用表单的内部CreateControl(bool fIgnoreVisible) 方法并将true 作为参数传递给它:

var f = new Form1();
var createControl = f.GetType().GetMethod("CreateControl",
    BindingFlags.Instance | BindingFlags.NonPublic);
createControl.Invoke(f, new object[] { true });

替代解决方案

  • 在调用方法之前显示Form。然后表单将在运行单元测试期间显示。

  • STA 线程中显示Form

示例

假设你的表单中有这样的方法:

public partial class Form1 : Form
{
    //...
    public int Method1(int i)
    {
        this.Invoke(new Action(() => { i++; }));
        return i;
    }
}

然后在你的测试项目中,可以使用如下代码:

[TestMethod]
public void TestMethod1()
{
    var f = new Form1();

    var createControl = f.GetType().GetMethod("CreateControl",
        BindingFlags.Instance | BindingFlags.NonPublic);
    createControl.Invoke(f, new object[] { true });

    var input = 0;
    var expected = 1;
    var actual = f.Method1(input);
    Assert.AreEqual(expected, actual);
}

【讨论】:

  • 另外,请确保您阅读了我添加的 Alternative Solutions 部分。
【解决方案2】:

没有实际代码很难判断,但这通常表明Test 方法中的代码不应该在表单中。

表单应该只是显示逻辑,而不是模型逻辑。

现在我还有一个列表框,它正在里面填充 我正在测试的功能。所以当我将方法分开时这是一个问题 另一个班级。

如果您用一些代码描述了问题,我们或许可以提供帮助。您可以使用事件或委托来解决它,以将视图逻辑排除在您的模型之外,反之亦然。

【讨论】:

    猜你喜欢
    • 2013-06-02
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 2019-02-12
    • 2015-03-30
    相关资源
    最近更新 更多