Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
* Adds a Java agent that sets a defaultUncaughtExceptionHandler for all jvm test modules,
* to ensure that exceptions thrown in Rx subscriptions (and coroutines?) aren't lost.
*
* Usually, one would do this with a JUnit RunListener, but Gradle doesn't support JUnit
* RunListeners, see https://github.com/gradle/gradle/issues/1330
*
* This workaround adds a test dependency for all modules to the module containing the uncaught
* exception handler. This module contains a Java agent, which is called before JUnit runs. To
* setup the agent we compile the jar and add the filepath as JVM argument.
*/
String defaultExceptionHandlerPath = ':path:to:java-agent:module'
Provider<Jar> jarTask
subprojects {
afterEvaluate { Project subproject ->
if (subproject.path == defaultExceptionHandlerPath) {
subproject.afterEvaluate {
jarTask = subproject.tasks.named('jar')
}
} else {
boolean isRealProject = project.plugins.hasPlugin('java') ||
project.plugins.hasPlugin('java-library') ||
project.plugins.hasPlugin('com.android.application') ||
project.plugins.hasPlugin('com.android.library')
// Add the dependency only if one of the plugins is applied.
if (isRealProject) {
dependencies {
testImplementation project(defaultExceptionHandlerPath)
}
}
}
subproject.tasks.withType(Test).configureEach {
doFirst {
jvmArgs "-javaagent:${jarTask.get().archiveFile.get().asFile}"
}
}
}
}
@jameswald
Copy link

jameswald commented Nov 27, 2019

This works for Android modules with Gradle test execution:

android {
  testOptions {
    unitTests {
      all {
        // Android Studio doesn't apply jvmArgs. The agent will only be used in CI.
        // https://issuetracker.google.com/issues/145231226
        jvmArgs "-javaagent:${project(':test:agent').jar.archivePath}"
      }
    }
  }
}

Android Studio fails to pick up jvmArgs either way. 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment