如何将unittest值取决于MessageBox?

时间:2015-05-12 05:48:59

标签: c# unit-testing nunit

我使用NUnit测试单位,我有一个方法:

class abc
{
    private int a;
    public void myMethod()
    {
         if(MessageBox.Show("Sure?", "Title", MessageBoxButtons.YesNo) == DialogResult.Yes)
             a = 1;
         else
             a = 0;
    }
}

如何编写NUnit来测试此方法?对不起我的英语不好。 非常感谢你。

2 个答案:

答案 0 :(得分:3)

通常的解决方案是模拟MessageBox类并模拟Show方法返回的内容。由于它是一种静态方法,因此需要在代码中进行额外的工作和一些修改。这是一个可能的解决方案:

创建一个封装Show方法的类:

public class MyMessageBox {
    public virtual DialogResult Show(string text, string caption, MessageBoxButtons buttons) {
        return MessageBox.Show(text, caption, buttons);
    }
}

然后修改您的代码以使用该类:

class Abc {
    internal int a;
    private readonly MyMessageBox messageBox;

    public Abc(MyMessageBox messageBox) {
        this.messageBox = messageBox;
    }

    public void MyMethod() {
        if (messageBox.Show("Sure?", "Title", MessageBoxButtons.YesNo) == DialogResult.Yes)
            a = 1;
        else
            a = 0;
    }
}

之后,您可以编写模拟MyMessageBox类的测试。我在下面的示例中使用NSubstitute

[Test]
public void Test() {
    MyMessageBox messageBox = Substitute.For<MyMessageBox>();
    messageBox.Show("Sure?", "Title", MessageBoxButtons.YesNo).Returns(DialogResult.Yes);

    Abc abc = new Abc(messageBox);
    abc.MyMethod();

    Assert.AreEqual(1, abc.a);
}

这是一种方法。由您来决定是否值得付出努力。

答案 1 :(得分:0)

我建议使用一些设计模式来实现这一目标。

- MVVM(你可以从Nuget获得一个名为MVVMLight的超级库)

- 依赖注入

- 控制倒置

- 存储库模式

因此,在顶级视图中只存在对MessageBox的调用。像这样的东西 -

Messenger.Default.Register<DialogMessage>(this, ProcessMessage);

    private static void ProcessMessage(DialogMessage message)
    {
        var result = MessageBox.Show(
                        message.Content,
                        message.Caption,
                        message.Button);

        message.Callback(result);
    }

所以,现在当你运行单元测试 -

    [Test]
    public void Some_Test ()
    {
        //Arrange
        string expected_msg = "";
        Messenger.Default.Register<DialogMessage>(this, (o) => {expected_msg=o.Content ;}); 
        CreateSUT();

        //Act
        ..do something here that involves calling that MessageBox

        //Assert

        Assert.That(expected_msg, Is.EqualTo(<Some Msg you are sending from ViewModel>));
    }

当从ViewModel以这样的方式调用时,此单元测试捕获对MessageBox的调用 -

Messenger.Default.Send(new DialogMessage("<Some Message you are sending from viewmodel>", delegate { })
            {
                Button = MessageBoxButton.OK,
                Caption = "Alert",
                Icon = MessageBoxImage.Exclamation
            });