2

I've uploaded a trivially-simple test project to gitlab that consists of two kotlin files.

Trivial.kt has a simple class:

package com.example
class Trivial {
    fun gus() {
        error("Behold my erroneousness!")
    }
}

And TrivialTests.kt has a simple test:

package com.example
import org.junit.Test
class TrivialTests {
    @Test
    fun testGus() {
        val din = Trivial()
        din.gus()
    }
}

The build.gradle file does apply plugin: 'kotlin' and lists the usual dependencies:

dependencies {
  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
  compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

  testCompile 'junit:junit:4.12'
  testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}

And, in gradle itself, this all does exactly what you'd expect. ./gradlew test dies with an IllegalStateException on my error call. But, now I want to debug that failed test using IntelliJ. So I use IntelliJ's "import project" feature. When it completes, a green arrow appears between the line numbers and the beginning of my test function, and right-clicking it gives me the option to debug my test. Choosing that option brings up the debugger, and immediately runs and fails the test.

I want to automatically break on exception, so I check "Any Exception"'s Enable button in the breakpoints window, and try to start the test again. I am immediately taken to the classloader, which is throwing a ClassNotFoundException for "org.groovy.debug.hotswap.ResetAgent". I click continue, and I get another ClassNotFoundException, and this goes on more times than I can count. Most of the exceptions are about org.junit classes, with occasional kotlin and gradle classes mixed in for flavor.

Using the class filter, I exclude exceptions raised from *ClassLoader from the breakpoint, and continue. The next stop is in java.lang.Integer which is raising a number format exception because intellij itself has tried to call Integer.parseInt("java/util/concurrent/CompletableFuture$UniRun"). It does this several more times with different type names, and then it's JUnit's turn, getting FileNotFoundExceptions for trying to open a properties file and a bunch of jars that don't exist.

A co-worker who works with me on many of the same projects is adamant he's never seen these exceptions, suggesting there's something wrong with my configuration, but I have not been able to find any intellij setting that seems to impact the outcome.

I can get the debugging behavior I want by whitelisting my package(s) -- adding a wildcard class filter to include only com.example*.

The question is: why are there so many nuisance exceptions when junit first starts?

Dan
  • 4,312
  • 16
  • 28
  • post the stacktrace – Meo Mar 08 '18 at 19:53
  • @Meo I pasted the stack trace of the first 10 `ClassNotFoundException`s into [a gitlab snippet](https://gitlab.com/drmoose/so-why-cant-i-debug-unit-tests/snippets/1702856) – Dan Mar 08 '18 at 20:23
  • As the jvm/junit starts there would be a myriad of exceptions that are caught and managed by the framework code. I'm sure you would get it same behaviour if you used pure java. If you enable "Any exception" in IntelliJ you'd get hundreds of these. It's nothing to worry about. There is no problem with your code and it's working as expected. – Strelok Mar 09 '18 at 01:18

1 Answers1

1

As @Strelok suggests in the comments, there isn't anything wrong with the code, and the menagerie of useless exceptions that get thrown by assorted internals when JUnit starts are just a normal part of its initialization.

My co-worker never saw these exceptions because he had "Caught Exceptions" unchecked in his exception breakpoint UI. The problem here is that IntelliJ doesn't special-case JUnit, and JUnit catches all exceptions that occur within a test, so unchecking that option results in the test failing without ever stopping at the breakpoint.

A better workaround for this problem was provided by Hans-Peter Störr in this answer:

"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.

Unfortunately there doesn't seem to be a way to make that the default, so it has to be done for every intellij project, but it does result in the debugger stopping only at the unhandled exception in my code.

Dan
  • 4,312
  • 16
  • 28