Assertion Swallowed By Its Own Catch

ID

java.assertion_methods_try_block_try

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

assertion, reliability, testing

Description

Reports a JUnit or AssertJ assertion, or a fail(…​) call, made directly in the try block of a try-catch whose matching catch clause targets AssertionError (or a broader type that also catches it, such as Error or Throwable) without ever referencing the caught exception.

Rationale

AssertionError is exactly what a failed assertion throws. Catching it right next to the assertion swallows the very failure the assertion exists to report, so the test passes whether or not the assertion actually held.

@Test
void rejectsInvalidInvoice() {
  try {
    validateInvoice(invoice);
    fail("Expected an AssertionError"); // caught below and discarded
  } catch (AssertionError e) {
  }
}

Remediation

Prefer the dedicated exception-testing API, or, if the try-catch is kept, inspect the caught exception to confirm it is the one expected.

@Test
void rejectsInvalidInvoice() {
  assertThrows(AssertionError.class, () -> validateInvoice(invoice));
}

@Test
void rejectsInvalidInvoiceWithMessage() {
  try {
    validateInvoice(invoice);
    fail("Expected an AssertionError");
  } catch (AssertionError e) {
    assertThat(e.getMessage()).contains("invalid");
  }
}

What is not reported

Only a call that runs as part of the try block’s own control flow counts: an assertion reached only through a nested method, lambda, or a local or anonymous class declared inside the try is not flagged, because that code executes later, if at all, not as part of the try. A catch clause targeting an unrelated exception type is out of scope; multiple catch clauses matching AssertionError or a supertype suppress the finding as soon as one of them references its exception, however lightly.

© 2026 Xygeni. All rights reserved