Reputation: 2255
I have an integration test that makes a form appear. It is not a coded UI test, it is just a test that happens to use a form. Lets not discuss now, that in general it is a good idea or not, it is in my case necessary.
If everything runs in order, then the form appears, some functions are called, the form is closed, assertions are made, and the unit test passes.
But, if something goes wrong ...
If an exception occures then instead of a failing unit test I got the "Unhadled exception occurred" dialog. This dialog of course stops the application, until somone clicks "ok" (and there is no one to click "ok" on a CI server), and after that the test passes. (Or at least it is marked green.)
The question is, how can I change back this behaviour?
After some research, I have found out, that there are 2 top level exception handlers, one for the application, and one for the UI thread.
I set them like this:
Application.ThreadException += (o, e) => MessageBox.Show("hello ui thread");
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += (o, e) => MessageBox.Show("hello app");
Then, when an exception occurres, I get the "hello ui thread" messagebox.
Can I set the Application.ThreadException
in a way, that it restores the original behaviour? Is there any other way to resolve this issue?
UPDATE
As some answerers pointed out I have a piece of really bad code in my hands, there is nothing to deny about it. Believe me, the fact thet the UI and the business logic in not adequately seperated is far not the worst thing about it.
I am not here to make excuses, but I can honestly state that it is not my fault. This piece of code was written by someone I have never met, and does not work at my company anymore. (For a damn good reason.)
There is no adequate documentation nor specification about what this code does, but it is sadly an important part of the software, we can't afford breaking it, or make it any more broken than it is now.
I have to refactor it, yes. I *am* refactoring it. But for that I need to write some tests first. And to write some test, I need do refactor it. It is the case of the egg and the chicken.
Right now I do not need general advice about good software design. I do not need judgement about the situation I am in. I need a specific technical answer to a specific technical question I asked.
OFF
About the "if you were one of my developers" comment. I think you would be really glad to have a developer who cleans up the mess that someone else made.
Upvotes: 1
Views: 157
Reputation: 2255
With this peice of code I can rethrow the exception from the UI thread on the main thread:
[TestMethod]
public void Test1()
{
Exception thread_ex = null;
ThreadExceptionEventHandler eventHandler = (o, e) =>
{
thread_ex = e.Exception; //store the exception from the UI thread
Application.ExitThread(); //kill the UI thread
};
Application.ThreadException += eventHandler;
DoTest(); //do the test
Application.ThreadException -= eventHandler;
if (thread_ex != null) //if an exception was stored
throw thread_ex; //throw it again on the main thread
}
Because I use the Application.ThreadException
, the "Unhandled exception occurred" dialog will not appear.
Upvotes: 1
Reputation: 5313
Running any type of UI test on a CI server is not a good idea because of the exact behavior that you are seeing. Changing production code to suit your tests is not a good idea either.
If I were in this situation I would do two things. First, I would refactor the code to ensure that as much of the functionality of the form could be driven without the UI in the form of standard unit tests. This could be in the form of a presenter, controller or view model of some kind.
Second, I would remove the integration test that uses the actual form from the CI suite and only run it manually as part of a final integration suite that ensures that the view model is wired correctly.
In your case, if you set up your logic module such that if all the tests pass the form test won't throw any exceptions, then you can go ahead and run your tests at this point if you set up your form test to not run if the previous tests fail.
Upvotes: 1