How to make Application.Run() testable

102 Views Asked by At

I am currently writing system tests for a legacy windows forms application.

In my test, I call the Program.Main() method, which in turn calls Application.Run(new MainForm()); at some point.

Is there a way to replace Application.Run() with something that I can control?

Specifically, I need to be able to stop the execution and catch unhandled exceptions.

2

There are 2 best solutions below

0
On

You could modify Program.Main to accept a form as an input parameter, with a default of MainForm. Reference types can't have non-null defaults but we can accomplish the same thing by using two prototypes:

class Program
{
    //Normal entry point
    static public void Main()
    {
        Main(new MainForm());
    }

    //Internal & test entry point
    static public void Main(Form form)
    {
        DoSomeSetup();
        Application.Run(form);
    }
}

When you run the program in the normal way, it'll use a MainForm.

But when you run it from your test project, you can call it like this:

Program.Main(new FormICanControl());

And then you can control it.

//Arrange
var t = new TestForm();

//Act
Program.Main(t);
t.ExecuteSomeTest();

//Assert
Assert.AreEqual(t.ResultCode, 0, "Test failed.");
0
On
  1. To "stop the execution", you can ask Main thread to exit by calling Application.ExitThread() and in dreadful situations when it does't respond you may kill the Main thread with .Abort() as a last resort.
  2. The exceptions won't be automatically collected for you anywhere, but you can catch them in a process of testing using

Application.ThreadExceptionHandler

AppDomain.CurrentDomain.UnhandledException

  1. Testing a real-life app without Application might be a problem because people often do some tricks by calling Application.DoEvents(..) and doing other stuff with messages pump.