How to use XCTAssertThrowsSpecific - ios

I'm writing Cocoa unit tests using XCTest and recently used XCTAssertThrows for the first time. That's pretty cool, but I want to make it even better with XCTAssertThrowsSpecific and requiring a certain exception.
Here is an example test:
-(void)testShortPassword {
XCTAssertThrows([user storePassword:#"abc"],#"Expect exception for short pw");
}
And on my user class I have the following code:
-(void)storePassword:(NSString*)password {
NSCAssert(password.length > 6, #"Password must be longer than 6 characters");
// go on to store the password on the keychain
}
Keeping in mind that Cocoa in general shies away from using exceptions (so it might be better to return an error, and show UI in the preceding example, etc.) How do I throw an exception in a manner that can be caught by XCTAssertThrowsSpecific? How do I specify that in XCTAssertThrowsSpecific(expression, specificException, format...)?

You should only use exceptions for exceptional cases, not for error handling and flow control
Having said that, here's how you use XCTAssertThrowsSpecific:
XCTAssertThrowsSpecific expects the specific class of the exception as the second parameter. NSCAssert throws an NSException. To test for that, use
XCTAssertThrowsSpecific([object methodThatShouldThrow], NSException, #"should throw an exception");
Now, that won't help much, because it's likely that every exception is an NSException or a subclass thereof.
NSExceptions have a name property that determines the type of the exception. In case of NSCAssert this is NSInternalInconsistencyException. To test for that, use XCTAssertThrowsSpecificNamed
XCTAssertThrowsSpecificNamed(
[object methodThatShouldThrow],
NSException,
NSInternalInconsistencyException,
#"should throw NSInternalInconsistencyException"
);

Related

exception types in exception handling

if error handling in dart in the catch block chain applies the supertype first and then the subtypes in subsequent catch blocks, then the catch blocks corresponding to the subtypes will never work. In visual studio code, a warning is displayed in these cases. I believe a static error should be generated.
class A implements Exception {}
class B extends A {}
void main() {
try {
var x = 1;
} on A {
} on B {
// warning
} on Exception {} // warning
}
Is it possible to configure the analyzer so that an error is generated instead of a warning?
Why isn't this done by default?
Is it possible to configure the analyzer, compiler so that block reordering is performed automatically by the dart fix command, for example?
I would like to get an error with the wrong catch order, as well as the possibility of its automatic correction.
Found a way to generate an error if some of the catch blocks will never be executed due to the fact that the base class can be in the first catch block, and the child class will already be in the second.
Requires setting in analysis_options.yaml file.
analyzer:
errors:
dead_code_catch_following_catch: error
But I have not yet found a way to automatically reorder catch blocks. If someone finds it would be great. In general, it would be possible at the level of the dart compiler to consider the possibility of introducing a mechanism in which the catch blocks of child classes would always be performed first before the catch blocks of parent classes.

throw Exception('oops!') vs throw 'oops!'

I notices some code that made me think the Exception function call was optional? E.g., do these two lines perform the same function?
throw Exception('oops!');
throw 'oops!'
No.
The former, throw Exception('oops!');, creates a new Exception object using the Exception constructor, then throws that object.
It can be caught by try { ... } on Exception catch (e) { ... }.
The latter, throw 'oops!'; throws the string object.
It can be caught by try { ... } on String catch (e) { ... }.
Generally, you shouldn't be doing either.
If someone made an error, something that would have been nice to catch at compile-time and reject the program, but which happens to not be that easy to detect, throw an Error (preferably some suitable subclass of Error).
Errors are not intended to be caught, but to make the program fail visibly. Some frameworks do catch errors and log them instead. They're typically able to restart the code which failed and carry on, without needing to understand why.
If your code hit some exceptional situation which the caller should be made aware of (and which prevents just continuing), throw a specific subclass of Exception, one which contains the information the caller needs to programmatically handle that situation. Document that the code throws this particular exception. It's really a different kind of return value more than it's an error report. Exceptions are intended to be caught and handled. Not handling an exception is, itself, an error (which is why it's OK for an uncaught exception to also make the program fail visibly).
If you're debugging, by all means throw "WAT!"; all you want. Just remove it before you release the code.

Is it possible to determine if an Objective-C exception will be caught?

I'm running into a situation in iOS (and OS X) where exceptions from NSKeyedUnarchiver cause binary-only third-party frameworks to crash my app (when deployed in the field) when they try to unarchive a corrupt archive, thus forcing users to delete and reinstall the app. This doesn't happen often, but I'd like that number to be zero.
I can't solve the problem by wrapping the NSKeyedUnarchiver calls, both because I don't have the source code and because those calls are not the direct result of anything that my code does; they run on arbitrary background threads at arbitrary times.
I'm currently swizzling the NSKeyedUnarchiver class so that reading a corrupt archive returns nil (as though the file were not there) rather than throwing an exception, but I can't be certain whether any of those third-party frameworks might do things correctly (with an #try/#catch block) and might break in interesting ways if I do so.
It would be helpful if I could somehow examine the Objective-C exception handling tree (or equivalent) to determine whether an exception handler would catch an exception if thrown, and if so, which handler. That way, my patched method could return nil if the exception would make it all the way up to Crashlytics (which would rethrow it, causing a crash), but could rethrow the exception if some other handler would catch it.
Is such a thing possible, and if so, how?
Why not wrap your exception-throwing callsite in a try/catch/finally?
#try {
//call to your third party unarchiver
}
#catch {
//remove your corrupted archive
}
#finally {
//party
}
Rolling your own global exception handler may also be of use here, ala: How do you implement global iPhone Exception Handling?
If you're not sure that wrapping third-party library code with #try/#catch is good enough you can hook NSKeyedUnarchiver methods to replace them with exact same wrapper thus making sure that exception is never gets thrown outside. Here is pseudo-code:
#try {
//call original NSKeyedUnarchiver implementation
}
#catch {
return nil;
}
Objc runtime has public APIs that can do such a thing

Do not stop test execution on XCTAssertThrowsSpecific

Using XCTest, a test does the following:
XCTAssertThrowsSpecificNamed([does something that breaks], NSException, NSInvalidArgumentException);
I don't want the debugger to stop on the NSException that I know will occur but I want it to still stop on other exceptions that might occur.
Basically we don't have a choice. I still consider it an xCode bug because you already told xCode an exception will be thrown, and what exception it will be. Why provide XCTAssertThrows if it's an exception you're not "expecting"?
Obviously it's for exceptions you are expecting, which #nhgrif argues should be an error, not an exception. Might be a good point, but i do want my program to crash if this case ever happens, because I can't handle it.
So the real question is more why not disable the debugger on that exception only? Probably because they haven't gotten around to it. I'd suggest opening a bug/feature request with Apple. I'd love for someone to contradict me on this (please comment!) but until then, I'll live with this issue (disable debugger when running all my tests).
--> https://stackoverflow.com/a/22393643/1701430
"Why does the test stop when the execution is thrown?"
Because you have a breakpoint, which stops execution.
"Why, after removing the breakpoint, does my application crash when the exception is thrown?"
Because you have an unhandled exception. Unhandled exceptions cause your program to crash.
"How can I handle an exception so it won't crash my program?"
The easy answer to this question is to simply NOT throw an exception. In other programming languages, like Java, this is perfectly standard. But in Objective-C, we don't really do exceptions. In Objective-C, exceptions should be saved for TRULY exceptional behavior.
With that said, and a strong suggestion for you to find another way to handle whatever it is you're trying to handle, this is how you handle an exception in Objective-C:
#try {
// code that could throw an exception
}
#catch (NSException *e) {
// handle the exception...
}
#finally {
// post try-catch code, executed every time
}

BlackBerry - global exception handler

(edit: this question is about BB specifically, because of the strange way it optimises exceptions. I am comfortable with normal exception handling patterns in J2SE, but BB does not behave as per normal. Specifically in this case, BB discards the error type, and message, and how BB devs try to deal with this issue, or if they ignore it.)
I would like to implement some form of custom global error handling in my BB app. Specifically to try to handle any other exceptions that were not caught by my code, because I had not expected them. The default behaviour is that the app fails, and a dialog pops up saying an Unknown error occured.
I would like to describe the error a little bit better, hence my term "global error handler". Something similar to the code:
public static void main(String[] args)
{
try
{
FusionApp app = FusionApp.getInstance();
app.enterEventDispatcher();
}
catch (Throwable t)
{
// t has lost all type information at this point - this prints "null"
System.err.println(t.getMessage());
}
}
My immediate problem is that when I catch t (in the main() method after the app.enterEventDispatcher() call), it has lost its type information. e.g. I know that the code throws an IllegalArgumentException with a custom message - however in the catch block, it is a java.lang.Error with null message.
And in the stack trace (ALT LGLG), the message has also been lost (at least the stack trace is accurate).
So... what is a good pattern to use to implement some form of global error handling on BB? Or is this considered a bad idea on this platform?
Is it considered good practice to just have the unknown error dialog box pop up - I don't like this, but maybe that is the way of the BB?
Best practices are to implement custom exception handling.
So, if you expecting to catch IllegalArgumentException, MyCustomException and StartupException, put them into catch block first, and then put an Exception catch (and then, if you like, put a Throwable catch)
The common rule is - from most exclusive to most common, and for exceptions of the same level - from most expected to least expected.
In case of exception == null or getMessage() == null you can always display something like "Application error, please send event log to [support email]" message, then if you have a nice event logging in you app, you have a good chance to reproduce an issue.
And talking about event log, see EventLogger class to implement logging.

Resources