C# – Advice on Unit testing a Windows Forms application

cunit testingwinforms

I have written a Windows Forms application and now I want to write some unit tests for it (not exactly test driven development seeing as I am writing the tests after I have developed but better late then never!) My question is that with such an application how do you go about writing the unit tests, given that nearly all of the methods and events are private? I have heard of NUnit Forms but I hear good and bad things about it, also there has been no real development on that project for a while so it looks abandoned. Also is it generally accepted that the project have have adequate unit testing in place if I wrote unit test cases for all of the events that a user would trigger by clicking/ pressing buttons, or would I have to go and write unit test cases for all methods and figure out a way to test my private methods?

EDIT: My business logic is seperated from my presentation logic, there is 1 or 2 public methods my business logic exposes so the form can access them, but what about all the private methods that are in the business logic?

Best Answer

The key to Unit Testing graphical applications is to make sure that all most all of the business logic is in a separate class and not in the code behind.

Design patterns like Model View Presenter and Model View Controller can help when designing such a system.

To give an example:

public partial class Form1 : Form, IMyView
{
    MyPresenter Presenter;
    public Form1()
    {
        InitializeComponent();
        Presenter = new MyPresenter(this);
    }

    public string SomeData
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            MyTextBox.Text = value;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Presenter.ChangeData();
    }
}

public interface IMyView
{
    string SomeData { get; set; }
}

public class MyPresenter
{
    private IMyView View { get; set; }
    public MyPresenter(IMyView view)
    {
        View = view;
        View.SomeData = "test string";
    }

    public void ChangeData()
    {
        View.SomeData = "Some changed data";
    }
}

As you can see, the Form only has some infrastructure code to thy everything together. All your logic is inside your Presenter class which only knows about a View Interface.

If you want to unit test this you can use a Mocking tool like Rhino Mocks to mock the View interface and pass that to your presenter.

[TestMethod]
public void TestChangeData()
{
    IMyView view = MockRepository.DynamickMock<IMyView>();
    view.Stub(v => v.SomeData).PropertyBehavior();

    MyPresenter presenter = new MyPresenter(view);

    presenter.ChangeData();

    Assert.AreEqual("Some changed data", view.SomeData);
}