【问题标题】:Unit test a dynamically populating user control in WinForms在 WinForms 中对动态填充的用户控件进行单元测试
【发布时间】:2016-11-01 11:58:33
【问题描述】:

我有一个实现了 MVP 模式(被动视图)的 WinForms 项目。

我认为当涉及到用户控件时,我的模式存在问题,这是我在单元测试期间发现的

由于在我的视图中触发了一个事件,我在表单上放置了一个用户控件。该用户控件根据从视图中获得的数字为自己添加一定数量的标签、文本框等。最后,它告诉视图将用户控件添加到视图中。

我想对这个类中的逻辑进行单元测试,因为这是我认为最重要的测试。我只是不知道该怎么做,因为这个类中有逻辑和表单控件。我目前正在使用 Moq 来创建我的单元测试。

我通常会创建一个 Mock 对象来表示视图,然后单独测试要测试的对象中方法的实现。但是,由于我在这个类中创建了控件,我认为我不能像这样测试它(不包括 .Forms 库)。

希望有人知道解决办法。

编辑:我一直在尝试将我的逻辑与控件操作分开,但我正在努力解决我在原始用户控件代码下方发布的不同用户控件的功能。由于我遍历了一个控件列表,所以我不知道如何将其分成逻辑和控件处理。

用户控制代码

public partial class DetailScreenUserControl : UserControl
{
    // Private members.
    private readonly IDetailScreenView _view;
    private List<ComboBox> maturityInput = new List<ComboBox>();
    private List<ComboBox> complianceInput = new List<ComboBox>();

    // Public members.
    public List<string> MaturityInput
    {
        get
        {
            var list = new List<string>();
            for (int i = 0; i < maturityInput.Count; i++)
            {
                list.Add(maturityInput[i].Text);
            }
            return list;
        }
        set
        {
            for (int i = 0; i < maturityInput.Count; i++)
            {
                maturityInput[i].DataSource = new List<string>(value);
            }
        }
    }
    public List<string> ComplianceInput
    {
        get
        {
            var list = new List<string>();
            for (int i = 0; i < complianceInput.Count; i++)
            {
                list.Add(complianceInput[i].Text);
            }
            return list;
        }
        set
        {
            for (int i = 0; i < complianceInput.Count; i++)
            {
                complianceInput[i].DataSource = new List<string>(value);
            }
        }
    }

    // Initialize user control with IDetailScreenView. Subscribe to necessary events.
    public DetailScreenUserControl(IDetailScreenView view)
    {
        InitializeComponent();
        _view = view;
        _view.InitializingUserControl += InitializeUserControl;
    }

    // Initializes the user control for the detail screen.
    public void InitializeUserControl(object sender, EventArgs e)
    {
        List<string> qStandards = _view.SelectedQuestionStandards;
        Controls.Clear();
        maturityInput.Clear();
        complianceInput.Clear();

        int inputSeparation = Height / 2;
        int spacing = Width / 20;

        Size = new Size(_view.RightUserControlBoundary - Location.X, Size.Height);

        for (int  i = 0; i < qStandards.Count; i++)
        {
            Panel inputPanel = new Panel();
            inputPanel.BackColor = Color.AliceBlue;
            inputPanel.Location = new Point(0, i * inputSeparation);
            inputPanel.Size = new Size(Width - spacing, inputSeparation);
            Controls.Add(inputPanel);

            Label qs_label = new Label();
            qs_label.AutoSize = true;
            qs_label.Location = new Point(0, 0);
            qs_label.Font = new Font("Arial", 12F, FontStyle.Bold);
            qs_label.AutoSize = true;
            qs_label.Text = qStandards[i].ToString();
            inputPanel.Controls.Add(qs_label);

            Label m_label = new Label();
            m_label.AutoSize = true;
            m_label.Location = new Point(0, qs_label.Bounds.Bottom + qs_label.Height / 2);
            m_label.Font = new Font("Arial", 12F, FontStyle.Regular);
            m_label.Text = "Maturity standard";
            inputPanel.Controls.Add(m_label);

            Label c_label = new Label();
            c_label.AutoSize = true;
            c_label.Location = new Point(0, m_label.Bounds.Bottom + qs_label.Height / 2);
            c_label.Font = new Font("Arial", 12F, FontStyle.Regular);
            c_label.Text = "Compliance standard";
            inputPanel.Controls.Add(c_label);

            ComboBox m_input = new ComboBox();
            m_input.AutoSize = true;
            m_input.Location = new Point(c_label.Bounds.Right + 2 * spacing, m_label.Bounds.Top);
            m_input.Font = new Font("Arial", 10F, FontStyle.Regular);
            m_input.DropDownStyle = ComboBoxStyle.DropDownList;
            m_input.Size = new Size(inputPanel.Size.Width - m_input.Bounds.Left, spacing);
            maturityInput.Add(m_input);
            inputPanel.Controls.Add(m_input);

            ComboBox c_input = new ComboBox();
            c_input.AutoSize = true;
            c_input.Location = new Point(c_label.Bounds.Right + 2 * spacing, c_label.Bounds.Top);
            c_input.Font = new Font("Arial", 10F, FontStyle.Regular);
            c_input.DropDownStyle = ComboBoxStyle.DropDownList;
            c_input.Size = new Size(inputPanel.Size.Width - c_input.Bounds.Left, spacing);
            complianceInput.Add(c_input);
            inputPanel.Controls.Add(c_input);

        }

        if(qStandards.Count != 0)
        {
            saveAssessmentButton.BackColor = System.Drawing.SystemColors.ButtonHighlight;
            Controls.Add(saveAssessmentButton);
            saveAssessmentButton.Location = new Point(this.Size.Width - saveAssessmentButton.Width - spacing, qStandards.Count * inputSeparation);
        }

        _view.AddUserControl();
    }

    // Tells the view to save the assessment.
    private void saveAssessmentButton_Click(object sender, EventArgs e)
    {
        _view.SaveAssessmentButtonClicked();
    }
}

其他用户控制功能('answers'为控件列表)

public void SaveResults()
{
    results = new List<string>();
    int questionNr = 0;

    for (int p = 0; p < questions.Count; p++)
    {
        for (int i = 0; i < questions[p].Count; i++)
        {
            bool unanswered = true;

            results.Add(questions[p][i]);

            for (int j = 1; j <= maturityAnswers[p].Count; j++)
            {
                var radioButton = (RadioButton)answers[questionNr][j];
                if (radioButton.Checked)
                {
                    results.Add(answers[questionNr][j].Text);
                    unanswered = false;
                }
            }
            if (unanswered == true)
            {
                results.Add("");
            }
            unanswered = true;

            for (int j = maturityAnswers[p].Count + 1; j <= (maturityAnswers[p].Count + complianceAnswers[p].Count); j++)
            {
                var radioButton = (RadioButton)answers[questionNr][j];
                if (radioButton.Checked)
                {
                    results.Add(answers[questionNr][j].Text);
                    unanswered = false;
                }
            }
            if (unanswered == true)
            {
                results.Add("");
            }

            results.Add(answers[questionNr][0].Text.Replace("'", "''"));

            questionNr++;
        }
    }

【问题讨论】:

    标签: c# winforms unit-testing moq mvp


    【解决方案1】:

    我想对这个类中的逻辑进行单元测试,因为那是我 思考是最重要的测试。我只是不知道该怎么做, 因为这个类中有逻辑和表单控件

    因此将它们分成不同的类并测试仅包含逻辑的类

    【讨论】:

    • 哈哈,是的,这似乎是合乎逻辑的事情,不是吗;p。只是这将是相当困难的,因为控制操作和逻辑是如此交织在一起,但我会试一试。我只是想到一个用户控件可以在没有单独的类的情况下包含自己的逻辑,但我想这是我的误解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2016-04-03
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    相关资源
    最近更新 更多