How to make Application.Run() testable

133 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
John Wu 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
Kostya 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.