Bird
Raised Fist0
JUnittesting~3 mins

Why Checking exception type hierarchy in JUnit? - Purpose & Use Cases

Choose your learning style10 modes available
The Big Idea

What if your tests could catch the exact error type every time without fail?

The Scenario

Imagine you have a big program that can throw many types of errors. You want to check if the program throws the right kind of error when something goes wrong. Doing this by running the program and watching for errors manually is like trying to catch a tiny fish with your bare hands in a big river.

The Problem

Manually checking errors is slow and easy to miss. You might see an error but not know if it is the exact type you expect or just a related one. This can cause confusion and bugs to slip through. Also, repeating these checks by hand every time you change code wastes a lot of time.

The Solution

Using JUnit to check exception type hierarchy lets you write clear tests that automatically verify if the thrown error is exactly the one you expect or a subtype. This saves time, reduces mistakes, and makes your tests reliable and easy to run again and again.

Before vs After
✗ Before
try {
  methodThatThrows();
  fail("Expected exception");
} catch (Exception e) {
  if (!(e instanceof SpecificException)) {
    fail("Wrong exception type");
  }
}
✓ After
assertThrows(SpecificException.class, () -> methodThatThrows());
What It Enables

You can confidently ensure your program throws the right errors, improving code quality and catching bugs early.

Real Life Example

When building a banking app, you want to check that withdrawing too much money throws an OverdraftException, not just any error. This test helps catch mistakes before customers see them.

Key Takeaways

Manual error checks are slow and error-prone.

JUnit's exception hierarchy checks automate and simplify this process.

This leads to more reliable and maintainable tests.

Practice

(1/5)
1. In JUnit, when you want to check if a method throws an exception of a specific type or any of its subclasses, which assertion method should you use?
easy
A. assertThrows()
B. assertEquals()
C. assertTrue()
D. assertNull()

Solution

  1. Step 1: Understand the purpose of assertThrows()

    assertThrows() is designed to check if a block of code throws an exception of a specified type or its subclass.
  2. Step 2: Compare with other assertions

    assertEquals() checks equality, assertTrue() checks boolean conditions, and assertNull() checks for null values, none of which check exceptions.
  3. Final Answer:

    assertThrows() -> Option A
  4. Quick Check:

    Exception type check = assertThrows() [OK]
Hint: Use assertThrows() to check exceptions and their subclasses [OK]
Common Mistakes:
  • Using assertEquals() to check exceptions
  • Confusing assertTrue() with exception checks
  • Expecting assertNull() to verify exceptions
2. Which of the following is the correct syntax to assert that a method throws a NullPointerException in JUnit 5?
easy
A. assertThrows(NullPointerException.class, () -> method());
B. assertThrows(NullPointerException, method());
C. assertThrows(() -> method(), NullPointerException.class);
D. assertThrows(method(), NullPointerException);

Solution

  1. Step 1: Recall assertThrows() method signature

    assertThrows() takes the exception class as the first argument and a lambda expression as the second.
  2. Step 2: Match the syntax

    assertThrows(NullPointerException.class, () -> method()); correctly uses assertThrows(NullPointerException.class, () -> method()); which matches the required syntax.
  3. Final Answer:

    assertThrows(NullPointerException.class, () -> method()); -> Option A
  4. Quick Check:

    Correct syntax = assertThrows(NullPointerException.class, () -> method()); [OK]
Hint: Exception class first, then lambda expression in assertThrows() [OK]
Common Mistakes:
  • Passing exception instance instead of class
  • Swapping argument order in assertThrows()
  • Not using lambda expression for the executable
3. Consider the following JUnit 5 test code:
assertThrows(RuntimeException.class, () -> { throw new IllegalArgumentException(); });

What will be the result of this test?
medium
A. Test fails with a compilation error
B. Test fails because IllegalArgumentException is not RuntimeException
C. Test passes because IllegalArgumentException is a subclass of RuntimeException
D. Test passes but warns about unchecked exception

Solution

  1. Step 1: Check exception hierarchy

    IllegalArgumentException extends RuntimeException, so it is a subclass.
  2. Step 2: Understand assertThrows behavior

    assertThrows(RuntimeException.class, ...) passes if the thrown exception is RuntimeException or any subclass.
  3. Final Answer:

    Test passes because IllegalArgumentException is a subclass of RuntimeException -> Option C
  4. Quick Check:

    Subclass exception passes assertThrows superclass check [OK]
Hint: assertThrows accepts subclass exceptions of the specified class [OK]
Common Mistakes:
  • Thinking exact exception type is required
  • Confusing subclass with unrelated exceptions
  • Expecting compilation error for subclass exceptions
4. Given this JUnit 5 test:
assertThrows(RuntimeException.class, () -> { throw new FileNotFoundException(); });

The test fails. What is the most likely reason?
medium
A. The lambda expression does not throw any exception
B. The test method does not declare throws IOException
C. FileNotFoundException is a checked exception and must be declared
D. FileNotFoundException is not a subclass of RuntimeException

Solution

  1. Step 1: Check exception hierarchy

    FileNotFoundException extends IOException, not RuntimeException.
  2. Step 2: Understand assertThrows behavior

    assertThrows(RuntimeException.class, ...) fails because the thrown exception is not RuntimeException or any subclass. Other options are incorrect: checked exceptions like FileNotFoundException do not require declaration in the test method when using Executable lambdas.
  3. Final Answer:

    FileNotFoundException is not a subclass of RuntimeException -> Option D
  4. Quick Check:

    Non-subclass exception causes assertThrows to fail [OK]
Hint: assertThrows requires the thrown exception to be the specified class or subclass [OK]
Common Mistakes:
  • Misidentifying exception subclass relationships
  • Ignoring checked exception declaration rules
  • Expecting runtime exceptions to behave like checked
5. You want to write a JUnit 5 test that passes if a method throws either an IOException or any of its subclasses, but fails for other exceptions. Which of the following is the best approach?
hard
A. Use assertThrows(Exception.class, () -> method()); and check instance with instanceof IOException
B. Use assertThrows(IOException.class, () -> method());
C. Use try-catch inside test and assert exception type manually
D. Use assertThrows(Throwable.class, () -> method());

Solution

  1. Step 1: Understand assertThrows behavior with superclass

    assertThrows(IOException.class, ...) passes if the thrown exception is IOException or any subclass.
  2. Step 2: Evaluate other options

    Use assertThrows(Exception.class, () -> method()); and check instance with instanceof IOException requires manual checks and complicates test; Use try-catch inside test and assert exception type manually is verbose; Use assertThrows(Throwable.class, () -> method()); is too broad and accepts all throwables.
  3. Final Answer:

    Use assertThrows(IOException.class, () -> method()); -> Option B
  4. Quick Check:

    Superclass in assertThrows covers subclasses [OK]
Hint: Use superclass exception in assertThrows to cover subclasses [OK]
Common Mistakes:
  • Using too broad exception classes
  • Manually checking exception types unnecessarily
  • Ignoring assertThrows built-in subclass support
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard