I am looking for a way to modify catch block depending on if it's executed during the unit test run开发者_如何学编程 or not. The purpose is basically to detect/setup mock expectations which are swallowed because catch doesn't rethrow.
I am using MSTest.
One obvious thing is using preprocessor but I don't think it works. Especially if to use DEBUG define. There should be an easy way to detect that, shouldn't it? I must have been looking for something wrong because I couldn't find much info on that.
try {...}
catch(Exception)
{
Log(...);
#if DEBUG
throw;
#endif
}
ANSWER: extract the body of the try
into another method and test that instead. Provided by Jon and Ritch. See discussion under Jon's answer. Though thanks everyone for the contribution.
How can you test the exception handling if you want to change the exception handling? Testing the altered behaviour doesn't test what would happen if you didn't alter the behaviour.
Hopefully your mocks have other ways of allowing you to validate expectations at the end of the test, so you can avoid the exception being ignored that way - and you should be testing that your Log and Fix really does happen when you want it to. (Testing logging is tedious and rarely worth it, but presumably Fix does something important.) You should also be testing that the exception isn't rethrown, if that's part of the design.
(As a side matter, catching ArgumentException
is usually a bad sign to start with. But maybe in this case it's due to a poorly-designed library you have to use.)
EDIT: Just as a thought, if you're going to be able to test Log and Fix, that means you have to be able to check whether or not they were invoked. In cases where you don't expect an exception to be thrown, you should be able to verify that they weren't called. If they were, you've effectively proved that an exception was thrown.
I still stand by what I said in my comment and Jon seems to agree with me: changing your code on-the-fly just for testing kind of beats the purpose of testing.
If you need to "comment out" some exception handling for your tests to be viable, it might be a sign that you are catching exceptions too early in your code.
Maybe you should refactor your code so that it will not be modified for testing and then design further tests up the call stack to verify that exceptions are handled as you expect it.
"#IF DEBUG" should be used with extreme caution. You are telling the tested code to act differently during test, thus rendering the test pretty close to useless. Catch specific exception types instead. No exceptions should just be caught silently - they must leave some kind of trail. So, either you throw an exception, or you do something that can be detected by outiders - including your test.
My advice would be to identify the different types of exceptions your code will encounter, and make a catch block for each. Remember that you can create your own exception types:
private class MyException: Exception
{
}
This can be used to organize your exeptions in groups that corresponds to the logic of your code.
If your program is not a windows- or a webservice, I would recommend that you do not catch the basic "Exception" type. This is based on the philosophy that if the program meets unexpected behavior, it should be felt loud and clear. In this context, exceptions should NOT be considered unexpected (i.e. when using a database, one should expect occasional connection problems, timeouts, user issues etc.).
精彩评论