Gradle and IntelliJ IDEA – JUnit System Properties

In several unit test case scenarios I had the need to inject system properties to make the tests work. This is done easily with gradle:

test {
    systemProperty "mySystemProperty", "myValue"
}

This is straightforward. To make it a little bit more useful we can extract system properties given to gradle and pass them onto the test like this:

ext {
    testProperties = [
            'javax.net.ssl.keyStore',
            'javax.net.ssl.keyStorePassword',
            'javax.net.ssl.keyStoreType',
            'javax.net.ssl.trustStore',
            'javax.net.ssl.trustStorePassword',
            'javax.net.ssl.trustStoreType'
    ]
}

test {
    project.testProperties.each {
        systemProperty it, System.getProperty(it)
    }
}

This is nice if your build environment defines these properties so you can pass them. Also, there are passwords within and we don’t want to put them into the build in cleartext.

Next thing to do is to incorporate the properties into IntelliJ IDEA. I really like it, when I can execute tests in my IDE and so do others:
http://blog.proxerd.pl/article/setting-system-properties-for-the-default-junit-run-configuration-in-intellij-from-gradle

Basically, we add the idea plugin to our gradle script and hook into the project file generation:

String createVmParameters(List keys) {
    keys.collect { key ->
        def value = System.getProperty(key)
        "-D$key=$value"
    }.join(" ")
}

idea.workspace.iws.withXml { XmlProvider provider ->
    Node node = provider.asNode()
    def runManager = node.component.find { it.'@name' == 'RunManager' }
    def defaultJUnitConf = runManager.configuration.find { it.'@default' == 'true' && it.'@type' == 'JUnit' }
    def vmParametersOption = defaultJUnitConf.option.find { it.'@name' == 'VM_PARAMETERS' }
    vmParametersOption.'@value' = createVmParameters(project.testProperties)
}

This hooks into the generation of the project file and modifies the xml. If all works ok you can generate your project files with a call to gradle idea.

apply plugin: 'java'
apply plugin: 'idea'

ext {
    testProperties = [
            'javax.net.ssl.keyStore',
            'javax.net.ssl.keyStorePassword',
            'javax.net.ssl.keyStoreType',
            'javax.net.ssl.trustStore',
            'javax.net.ssl.trustStorePassword',
            'javax.net.ssl.trustStoreType'
    ]
}

test {
    systemProperty "mySystemProperty", "myValue"
    project.testProperties.each {
        systemProperty it, System.getProperty(it)
    }
}

String createVmParameters(List keys) {
    keys.collect { key ->
        def value = System.getProperty(key)
        "-D$key=$value"
    }.join(" ")
}

idea.workspace.iws.withXml { XmlProvider provider ->
    Node node = provider.asNode()
    def runManager = node.component.find { it.'@name' == 'RunManager' }
    def defaultJUnitConf = runManager.configuration.find { it.'@default' == 'true' && it.'@type' == 'JUnit' }
    def vmParametersOption = defaultJUnitConf.option.find { it.'@name' == 'VM_PARAMETERS' }
    vmParametersOption.'@value' = createVmParameters(project.testProperties)
}

2 Replies to “Gradle and IntelliJ IDEA – JUnit System Properties”

  1. I understand, Gradle Tooling Api alwols to redirect output. try { //obtain some information from the build BuildEnvironment environment = connection.model(BuildEnvironment.class) .get(); //run some tasks connection.newBuild() .forTasks( tasks ) .setStandardOutput(System.out) .run(); } finally { connection.close(); }Automatic model refresh cycle:- Wait 5 seconds (configurable) after last edit- Save build.gradle file- Run build- Check for exceptions- Report to user if any- Update model if all looks goodSomething along those lines.Have a look at STS Gradle plugin, it works just fine, without verbose output, it runs on update, either when build.gradle is modified explicitly or with git pull/rebase.

    1. Thanks for the comment!

      I can’t see the connection between standard output and the environment variables. Maybe you can clarify a bit.

Comments are closed.