9

When an uncaught exception is thrown in my code, I am used to having the debugger stop at the throwing statement so that I can examine the local variables and the members of all objects involved at the moment that the exception was thrown. With IntelliJ Idea this can be accomplished by going to Run, View Breakpoints, selecting the Exception Breakpoints tab, checking Any exception, and making sure that the Caught exception checkbox is unchecked, while the Uncaught exception checkbox is checked. With Eclipse and with Visual Studio (for C#) it is something different, but along the same lines.

The ability to have the debugger behave this way is extremely useful; so useful in fact, that I structure the main loop of my programs accordingly: on the release version, the main loop is of course embedded inside a try-catch-all; but on the debug version, there is no try-catch block in the main loop, so that any exceptions that are not caught anywhere within my program will remain uncaught, so that the debugger will suspend my program at the moment that they are thrown.

When testing my Java classes with JUnit, however, I have a problem: the debugger does not stop on any exception. Instead, what happens is that not only expected, but also unexpected exceptions get automagically caught, and I am given a post-mortem exception stack trace to try and make sense out of. That's not very cool.

I used to think that this is happening because JUnit makes use of java.lang.reflect.Method.invoke(), which catches all exceptions and transforms them to TargetInvocationExceptions, but then I wrote my own custom JUnit runner, which knows my test class personally and directly invokes its methods without Method.invoke(), and the problem persists. This means that the problem lies high up within core JUnit.

So, does anyone else have the same problem? Does anyone know of a solution so that we can have the debugger suspend program execution on unexpected exceptions while testing with JUnit?

Related (unanswered) question: Suspend on uncaught runtime exceptions in Eclipse Junit test runner

Related (unanswered) question: How to break into debugger within a jUnit test case?

Related (partly answered) question: Break on Exception in Eclipse using jUnit (The accepted answer says that "if you debug a single method in jUnit, the breakpoints start to work. If an entire class or package is debugged in jUnit, the debugger doesn't work.")

Community
  • 1
  • 1
Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • What version of JUnit are you running? I can catch uncaught exceptions in my tests just fine, Eclipse Indigo Build 20110615-0604, JUnit 4. – Perception Nov 29 '12 at 23:50
  • 2
    I am using JUnit 4.8.1. Please note that this question is not about catching uncaught exceptions; It is about having the debugger suspend program execution on uncaught exceptions. In other words, it is about having the `throw` instruction behave like a breakpoint if the thrown exception is uncaught. – Mike Nakis Nov 30 '12 at 10:51
  • I guess I wasn't clear. My IDE (Eclipse Indigo), suspends execution automatically, if I tell it too, on caught/uncaught exceptions. Even when running a JUnit 4 test. – Perception Nov 30 '12 at 12:28
  • Oh, I see. That's interesting, I will check it and I will get back about it. – Mike Nakis Nov 30 '12 at 14:54
  • @Perception I have been unable to confirm your observation. However, I found a new piece of information and added it at the very end of my answer. (Running entire test suite vs. running single test.) Does this agree with your observation? – Mike Nakis Jun 10 '15 at 20:15

2 Answers2

1

I hope I understand the question correctly, so correct me if I'm wrong, but:

  • you have a test, which throws an exception, which you do not catch yourself (so it, in that sense, is uncaught)
  • when you debug this test with the JUnit4 testrunner, JUnit shows you that the test fails (it threw the exception)
  • but the thread is not suspended, which is what you want to achieve
  • even though you have preferences | java | debug | suspend execution on uncaught exceptions enabled

In that case, I believe this is the intended behavior, JUnit catches and swallows your exception, so it is not uncaught as far as eclipse is concerned, as described here https://bugs.eclipse.org/bugs/show_bug.cgi?id=414133

You can have eclipse suspend any way by setting up your own rules for suspending on caught exceptions. Debug perspective | breakpoint view | J! icon | check suspend on caught exception

Hirle
  • 188
  • 6
  • Your understanding of the question is correct. However, your proposed solution will not work, because thousands of exceptions (which are caught) are thrown, both in code that I have no control over, and in my code under normal operations, and also in my code for the purpose of testing the error checking and handling code. – Mike Nakis Jun 11 '15 at 14:58
  • I cannot even use class filters to at least take care of the exceptions that are thrown and caught by the java runtime, because sometimes exceptions thrown by the java runtime propagate to my code, and I would like the debugger to break right there where my code invokes the runtime method that threw, but java debuggers apparently have no notion of "break in my code only" as Microsoft Visual Studio does. – Mike Nakis Jun 11 '15 at 15:05
  • Ah yeah, I understand, and given the link I posted I guess your last sentence is correct, the eclipse debugger doesn't seem to have a notion of suspending only in your code. That seems to leave getting JUnit not to swallow your exceptions as your only option... I have no idea if thats possible... – Hirle Jun 11 '15 at 15:42
0

As a workaround for use when investigating a test failure, you could create an instance of the offending test class in main method and call its test method by hand with your exception breakpoints method (which is very cool by the way, thanks for the question). That way, the method isn't being called reflectively.

artbristol
  • 32,010
  • 5
  • 70
  • 103
  • 2
    Thank you for the reply, but as you say, this is not a real solution, it is a workaround. In fact, it is easier to just go to the line where the exception was thrown, (by clicking on the stack trace,) place a breakpoint there, and re-run. I just want to avoid having to do that. – Mike Nakis Nov 30 '12 at 10:58