0

I use NUnit to test unit and I have a method:

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

How do I write NUnit to test this method? Sorry for my English. Thank you very much.

Old Fox
  • 8,629
  • 4
  • 34
  • 52
Mr.T
  • 25
  • 4

2 Answers2

3

The usual solution for this would be to mock the MessageBox class and simulate what the Show method returns. Since it's a static method, it requires additional work and some modifications in your code. Here's a possible solution:

Create a class that encapsulates the Show method:

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

Then modify your code to use that class:

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;
    }
}

After that, you can write tests that mock the MyMessageBox class. I'm using NSubstitute in the example below:

[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);
}

That's one way to do it. It's up to you to decide if it's worth the effort or not.

Thiago Sá
  • 832
  • 9
  • 22
  • Hi Thiago, Thank you so much, and I have one question . In other program , I'm not allowed to change code . So do you have a other solution? My program is WPF project . Thank you so much. – Mr.T May 13 '15 at 01:45
  • You need to provide more information about your problem. If that's a whole new question, please write a new one following [these basic rules](http://stackoverflow.com/help/mcve). – Thiago Sá May 13 '15 at 02:01
0

I recommend using some design patterns to achieve this.

--MVVM(There is a superb library called MVVMLight that you can get from Nuget)

--Dependency Injection

--Inversion Of Control

--Repository Pattern

So, then a call to the MessageBox only exists in the top level view. Something like this--

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);
    }

So, now when you run the Unit Test--

    [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>));
    }

This Unit Test catches the call to MessageBox when called from ViewModel in a way like this--

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