Checked and unchecked exceptions, try-with-resources, AssertionError
Everything that can be thrown extends Throwable. There are two branches:
- Error — serious JVM failures (
OutOfMemoryError) andAssertionError, which assertion libraries throw. They are normally not caught. - Exception — what can be handled. Checked ones (for example
IOException,SQLException) the compiler forces you to handle or declare withthrows. Unchecked ones are subclasses ofRuntimeException(NullPointerException,IllegalArgumentException,IndexOutOfBoundsException); handling is optional.
Custom exceptions. In test code they are usually unchecked so as not to clutter signatures: class TestDataException extends RuntimeException. Always pass the cause so the stack trace is not lost:
try {
return mapper.readValue(Files.readString(file), User.class);
} catch (IOException e) {
throw new TestDataException("Failed to load test data: " + file, e);
}
try-with-resources automatically calls close() on objects that implement AutoCloseable (streams, database connections, clients), even if an exception occurred. Closing goes in reverse order of opening; an exception from close() does not overwrite the main one but is attached as suppressed.
What not to do in tests:
- An empty
catchor onlyprintStackTrace(): the failure vanishes, the test is green and the scenario was not executed. catch (Throwable)orcatch (Exception)around assertions:AssertionErroris anError, so the first form swallows it (the test "passes") while the second does not catch it and the test correctly fails.throws Exceptionon every method just to get rid of the compiler.
When to catch: when you can really react (a retry, an expected negative scenario, adding context). An expected failure is checked with assertThatThrownBy(...) (AssertJ) or assertThrows (JUnit), not with try/catch and fail().