8

When I have a JUnit test, I'd like the debugger to stop right at the point where any exception in the tested code is thrown that lets the test fail, in order to inspect what's wrong. Is there a possibility to configure IntelliJ's debugger to do that, and not break on other exceptions?

If I set an exception breakpoint on any uncaught exception, this doesn't work since the exception is caught by JUnit. If I try to have the breakpoint break also on caught exceptions with catch class org.junit., that doesn't work either, since the exception is caught and wrapped by Javas reflection mechanisms before it reaches JUnit. So I'm a bit at loss here - Eclipse just stops at the original exception.

CLARIFICATION: I am talking about exceptions in the code I test or code called from there, not about assertion failures in the tests. For example, consider these tests:

@Test
public void thisShouldBreak() {
    int i = 25 - 25;
    int j = 17 / i;
}


private void neverBreakHereSinceThisIsCaught() {
    int i = 14 - 14;
    int j = 29 / i;
}

@Test
public void thisShouldNotBreak() {
    try {
        neverBreakHereSinceThisIsCaught();
    } catch (ArithmeticException e) {
        // ignored or handled
    }
}

@Test
public void thisShouldNotBreakEither() {
    try {
        getClass().getDeclaredMethod("neverBreakHereSinceThisIsCaught").invoke(this);
    } catch (Exception e) {
        // ignored or handled
    }
}

I want IntelliJ to stop when executing test thisShouldBreak at the place where the ArithmeticException is thrown, so that I can inspect the value of i that caused the exception. However, I do not want IntelliJ to stop in neverBreakHereSinceThisIsCaught since the exception thrown there doesn't reach JUnit. I tried unsuccessfully: - an exception breakpoint on caught exceptions breaks in neverBreakHereSinceThisIsCaught, too, and loads of other places. - an exception breakpoint only on uncaught exception is never hit at all, since JUnit catches and wraps those exceptions. - a catch class filterorg.junit.*` breaks in lots of internal places of JUnit end Java reflection calls by JUnit, too.

Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139

5 Answers5

2

You could add a filter to check if the stack trace contains your package. It will probably make the execution slower, but it will not stop for JUnit initialisation exceptions that don't prevent test execution anyway, and it will stop only if the calls involve some of your classes. Something along the lines of:

condition

Morfic
  • 15,178
  • 3
  • 51
  • 61
  • Nice idea! I wasn't aware it was possible to add such complicated break conditions. It does solve the problem with exceptions thrown within JUnit code nicely, but it would also break on exceptions caught before they reach JUnit. Unfortunately I don't see how to solve this. Do you? – Dr. Hans-Peter Störr May 18 '17 at 19:42
  • @Dr.Hans-PeterStörr yeah, it's pretty flexible.Then you need to try and clarify what exactly it is that you're looking for. My initial understanding is that you wanted to break execution at the original point of any exception that originated in your code and the example above should be doing that (is it not? did I miss anything?). However your comment seems to suggest that you'd like to break at some point where exceptions reach the JUnit framework?! If possible, i think a simple example may aid in clearing any doubts. – Morfic May 18 '17 at 21:36
  • Nice! I clarified things a little, and this really seems to work, together with a catch class filter org.junit.runners.* . Since this is somewhat unexpectedly complicated, I experimented somewhat more - see my answer. That seems to work, too. – Dr. Hans-Peter Störr May 29 '17 at 07:47
2

This is what I did:

What you basically want to do is tell Intellij to stop on any exception (Caught & Uncaught) where the catch class filter is junit, so that caught exceptions only by junit cause the debugger the stop.

Here's my Intellij settings: Intellij breakpoint settings

You might run into a similar issue when you use a app server like Tomcat, which catches exception. The same way, you would filter the catch class by Tomcat packages.

Yamcha
  • 1,264
  • 18
  • 24
1

How I deal with this:

  1. Set Java Exception Breakpoint to java.lang.AssertionError

enter image description here

  1. Debug a test that fails, it will break inside Assertion.java

  2. Look at the debugger and navigate to the test you want to debug as shown here:

enter image description here

You can now check variables, evaluate expressions, etc in your test

Kotse
  • 418
  • 2
  • 8
  • Thanks for the answer, but I was talking about exceptions in my own code or code called from my own code, not assertion failures. But that might be a good idea for assertions, if an "uncaught exception" breakpoint doesn't work there. – Dr. Hans-Peter Störr May 18 '17 at 19:37
1

If you only need exceptions that are caught in JUnit, you can use "catch class filters" in exception breakpoint and specify a class inside JUnit where they are catched.

Egor
  • 2,474
  • 17
  • 19
1

After fiddling around for a while, the following seems to work best: "Any exception" Breakpoint on caught and uncaught exceptions with a catch class filter org.junit.runners.* and a class filter -org.junit.* to get rid of caught exceptions that are thrown by the JUnit mechanics itself.

A unconditional breakpoint on caught and uncaught AssertionError seems to be a good idea, too, to inspect the data in the local variables in the test itself when an assertion fails.

Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139