【问题标题】:get text from windows form messagebox and close it dynamicly从 Windows 窗体消息框中获取文本并动态关闭它
【发布时间】:2021-11-19 08:04:46
【问题描述】:

我尝试为 windows 窗体进行单元测试。某些窗体有显示消息框的代码。我想测试消息框文本并从单元测试中关闭消息框表单。我该如何制作它们?

public partial class Form1 : Form
{
    private void Form1_Load(object sender, EventArgs e)
    {
        MessageBox.Show("Form opened");
    }
}

    [TestMethod]
    public void Form1_Load()
    {
        Form1 form = new Form1();
        //How to find messagebox to test TEXT and close the MESSAGEBOX form?
    }

【问题讨论】:

  • 只需通过添加中间接口将您的代码与真实消息框解耦,然后为生产提供带有真实消息框的实现,并为测试提供您想要的任何检查(并且没有真实消息框)的模拟实现。有关示例,请参见此处:stackoverflow.com/questions/14297312/… 并查看一般的依赖注入实践。
  • 感谢您的回复。这很有帮助。我也想在单元测试时关闭消息框表单。
  • 如果您正确地完成了测试实施,您的测试中将根本没有真正的消息框,因此无需关闭任何东西。在测试环境中,你只是用一些虚假的实现来替换真实的消息框,它只是检查消息和其他消息框参数,根本不显示真实的消息框。

标签: c# winforms unit-testing messagebox


【解决方案1】:

我认为您不想测试 MessageBox 的功能,毕竟那是一种 windows 方法。你必须相信微软他们已经测试过这个类。

您想要测试的是,当您的表单加载时,它会向操作员显示一些信息。您想隐藏这是使用 MessageBox 完成的。这样做的好处是,如果您希望其他方法向操作员显示某些内容,您可以重复使用此方法。

另一个优点:您还可以更改向操作员显示事物的方式,而无需更改该方法的所有用户。例如,如果您想在警告操作员时发出哔哔声,或者您想记录操作员已确认阅读警告。如果您在单独的方法中执行此操作,则不必更改此方法的所有用户。

换句话说:您的表单有一个 OperatorInformer 对象(TODO:发明一个专有名称)。这个对象实现了一个接口:

interface IOperatorInformer
{
    void ShowMessage(string text, ...);
    void ShowWarning(string text, ...);
    void ShowError(string text, ...);
    ...
}

如果您需要了解语言,请考虑创建一个包含所有警告和错误的枚举。界面将是:

enum OperatoInformationId {...}
interface IOperatorInformer
{
    void InformOperator(OperatorInformationId id, ...);
    ...
}

OperatorInformer 的任务是将 OperationInformationId 转换为正确的文本,

class OperatorInformer : IOperatorInformer
{
    ...

    public static IOperatorInformer Default {get;} = new OperatorInformer;
}

此 OperatorInformer 可以使用 MessageBox.Show 显示所需的文本,以及所需的图标、声音、标题等。

这并不能解决测试显示MessageBox的问题,但是由于这是一个小类,出错的机会很小。如果您确实需要测试 OperatorInformer,请考虑使用接口 IMessageBox(将定义 MessageBox 方法)和类 MessageBox(将使用 System.Windows.Forms.MessageBox 显示消息)进行相同的操作。

class Form1 : Form
{
    // make sure there is always at least the default operator informer:
    public IOperatorInformer OperatorInformer {get; set;} = OperatorInformer.Default();

    ...
}

单元测试方法Form1_Load

定义接口 IOperatorInformer 后,您可以更改您的要求:

要求:当 Form1 加载时,方法 IOperatorInformer.ShowMessage 只被调用一次,带有文本“Form opens”、一个图标...和一个标题栏...

这样更容易进行单元测试:

class UnitTestInformer : IOperatorInformer
{
    public int CallCount {get; private set;} = 0;
    public string Text {get; private set;}
    public MessageBoxIcon Icon {get; private set;} = MessageBoxIcon.None;
    ...

    public void ShowMessage(string text, MessageBoxIcon icon, ...)
    {
        ++this.CallCount;
        this.Text = text,
        this.Icon = icon,
        ...
    }
}

您的单元测试(每个测试都只测试需求中的一件事)

[TestMethod]
public void Form1_Load_ShowsOperatorInputExactlyOnce()
{
    // Create a unitTestInformer and a Form1 that uses this UnitTestInformer
    UnitTestInformer unitTestInfomer = new UnitTestInformer();
    Form1 form = new Form1()
    {
        OperatorInformer = unitTestInformer;
    };
    form.Show();  // this should Load the form

    Assert.AreEqual(1, unitTestInformer.CallCount);
}

[测试方法] 公共无效 Form1_Load_OperatorInputText() {

    UnitTestInformer unitTestInfomer = new UnitTestInformer();
    Form1 form = new Form1()
    {
        OperatorInformer = unitTestInformer;
    };
    form.Show();

    Assert.AreEqual("Form opened", unitTestInformer.Text);
}

等等。也是图标和标题栏的单元测试

【讨论】:

    【解决方案2】:

    我的解决方案如下。感谢您的建议

    public partial class Form1 : Form
    {
        public Form1(){InitializeComponent();}
        internal bool is_Message_Show = true;
        internal string message_For_Test ;
        internal DialogResult dialogResult_From_Test;
        internal void btnAdd_Click(object sender, EventArgs e)
        {
            DialogResult result = DialogResult.No;
            if (is_Message_Show)
            {
                result = MessageBox.Show("Do you want to add", "WARNING", MessageBoxButtons.YesNo);
            }
            else
            {
                result = dialogResult_From_Test;
            }
            if (result == DialogResult.Yes)
            {
                
            }
        }
    
        internal void btnDelete_Click(object sender, EventArgs e)
        {
            string message = "Deleted";
            if (is_Message_Show)
            {
                MessageBox.Show(message);
            }
            else
            {
                message_For_Test = message;
            }
        }
    }
    
        [TestMethod]
        public void btnAdd_Click_Yes()
        {
            Form1 form = new Form1();
            form.is_Message_Show = false;
            form.dialogResult_From_Test = System.Windows.Forms.DialogResult.Yes;
            form.btnAdd_Click(null, null);
            
        }
        [TestMethod]
        public void btnDelete_Click()
        {
            Form1 form = new Form1();
            form.is_Message_Show = false;
            form.btnDelete_Click(null, null);
            Assert.AreEqual("Deleted", form.message_For_Test);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多