nu.studer.credentials 在 Spock 内部不起作用

nu.studer.credentials does not work from inside Spock

我正在构建一个 Gradle 插件,它需要用户名和密码才能访问外部资源;为了避免使用明文密码,我使用插件 nu.studer.credentials.

为了测试我的插件,我使用了 Spock;以下测试文件 CredentialsFunctionTest.groovy 被剥离为仅相关部分,以显示问题:

package my.gradle.plugin

import org.gradle.testkit.runner.GradleRunner
import spock.lang.Specification
import spock.lang.TempDir

/**
 * A simple functional test for the credentials acquisition.
 */
class CredentialsFunctionalTest extends Specification {
    @TempDir
    private File projectDir

    private getBuildFile() {
        new File( projectDir, "build.gradle" )
    }

    private getSettingsFile() {
        new File( projectDir, "settings.gradle" )
    }

    def "can run task"() {
        given:
//---> Begin of settings file <------------------------------------------------
        settingsFile << """
plugins {
    id  'nu.studer.credentials' version '3.0'
}

"""
//---> End of settings file <--------------------------------------------------

//---> Begin of build file <---------------------------------------------------
        buildFile << """
plugins {
    id  'nu.studer.credentials'
}

String username = credentials.forKey( 'myUser' )
System.out.printf( 'Username: %s%n', username )
String password = credentials.forKey( 'myPassword' )
System.out.printf( 'Password: %s%n', password )

task doSomething {
} 
"""
//---> End of build file <-----------------------------------------------------

        when:
        def runner = GradleRunner.create()
        runner.forwardOutput()
        runner.withPluginClasspath()
        runner.withArguments("doSomething" )
        runner.withProjectDir( projectDir )
        def result = runner.build()

        then:
        result.output.contains( "Alive!" )
    }
}

“用户名”和“密码”的输出是 null – 这样的测试失败是预料之中的,因为字符串 "Alive!" 的任何地方都没有输出。

当我将文件 settings.gradlebuild.gradle(下面的内容)放置到一个空文件夹中,并使用 gradle doSomething 调用 gradle 时,我得到了预期的输出。

settings.gradle:

plugins {
    id  'nu.studer.credentials' version '3.0'
}

build.gradle:

plugins {
    id  'nu.studer.credentials'
}

String username = credentials.forKey( 'myUser' )
System.out.printf( 'Username: %s%n', username )
String password = credentials.forKey( 'myPassword' )
System.out.printf( 'Password: %s%n', password )

task doSomething {
} 

nu.studer.credentials 插件将值存储在 $GRADLE_USER_HOME/gradle.encrypted.properties 中,因此一个假设是 Spock 使用不同的临时用户 and/or 主文件夹。

根据 Leonard Brünings 在他对我的问题的评论中给我的提示,我能够确定问题并制定解决方案。

正如伦纳德所说,问题不在于 Spock 本身,而在于执行测试的 GradleRunner:这将使用与 [= 不同的“Gradle 用户主目录” 32=] Gradle 执行.

使用参数-g--gradle-user-home,可以更改,但不建议在测试Gradle插件时使用此指向默认位置(我们正在使用 Gradle 来测试 Gradle ……)。

幸运的是,nu.studer.credentials 插件提供了一个配置参数,允许指定保存加密凭据的文件的位置:-PcredentialsLocation=<path>.

所以解决方案看起来像这样(我只从原始测试脚本中提取了 when: 部分):

…
when:
def runner = GradleRunner.create()
runner.forwardOutput()
runner.withPluginClasspath()
runner.withArguments( "-PcredentialsLocation=%s/.gradle".formatted( System.getProperty( "user.home" ) ), "doSomething" )
runner.withProjectDir( projectDir )
def result = runner.build()
…

当然,测试仍然失败,但它现在显示 usernamepassword!

的正确值