1. Introduction

In Kotlin projects, the gradle.properties file is primarily used for storing build configuration values. These include settings for the build process, such as version numbers, JVM arguments, and other build-specific parameters. Because this configuration file is intended for the build process, we should be intentional and careful about accessing any of these properties outside the Gradle build tool.

In this tutorial, we’ll explore several methods to retrieve custom properties defined in gradle.properties within a Kotlin application, focusing on approaches that align with best practices. We’ll ensure that these methods involve accessing build properties safely, without directly accessing the gradle.properties file from production code.

2. Using the System.getenv() Method

The System.getenv() method is useful for retrieving properties set as environment variables during the build process. This approach is particularly beneficial in Continuous Integration/Continuous Deployment (CI/CD) pipelines, where environment variables are commonly used for configuration.

However, it’s crucial to understand that while these environment variables may be accessible during testing, they often won’t be available in the runtime environment due to the separation between build and runtime environments in Java and Kotlin.

In Gradle, we can set environment variables directly in our build.gradle.kts:

tasks.withType<Test> {
    environment("CUSTOM_PROPERTY", project.findProperty("custom.property") as String)
    environment("API_URL", project.findProperty("api.url") as String)
}

This method works because Gradle executes the tests as part of the build process, allowing it to set environment variables directly. Gradle controls the test lifecycle and injects these environment variables into the test environment, allowing the tests to access them.

Now, let’s see how we can retrieve values for these environment variables in a unit test:

@Test
fun `obtain environment variables using System getenv method`() {
    val customProperty = System.getenv("CUSTOM_PROPERTY")
    val apiUrl = System.getenv("API_URL")

    assertEquals("CustomValue", customProperty)
    assertEquals("https://api.example.com", apiUrl)
}

This code snippet ensures that our tests can access these environment variables correctly. However, we must be cautious not to rely on this approach for accessing build properties in production code.

3. Using a Generated Properties File

The way to access properties from gradle.properties in production code is by generating a custom properties file during the build process. This approach ensures that our configuration will exist because the original gradle.properties file will not be in the final build artifact.

3.1. Defining the Gradle Task

First, let’s define a custom Gradle task in the build.gradle.kts file. This task will generate a properties file based on the contents of gradle.properties:

tasks.register<Copy>("generateCustomProperties") {

The custom Gradle Copy task reads the original gradle.properties file located at the root of our project and copies it into the src/generated/resources directory under the new name custom.properties. This approach ensures that our properties are available in the generated resources, which can then be used in the final build.

3.2. Integrating the Task into the Build Process

Next, we’ll add the generated resources directory to our main source set. This ensures the file will end up in our final production artifact:

sourceSets {
    main {
        resources.srcDir("src/generated/resources")
    }
}

By including src/generated/resources in the main source set, the build process automatically recognizes and includes the custom.properties file in the final artifact. This approach ensures that the file is available in the classpath for both runtime and testing.

3.3. Unit Test

Now, let’s also create a unit test to verify that the properties from the generated file load correctly:

@Test
fun `obtain custom property value by loading properties from generated file`() {
    val propertiesFileUrl = this::class.java.classLoader.getResource("custom.properties")
        ?: throw IllegalStateException("Properties file not found")

    val properties = Properties().apply {
        propertiesFileUrl.openStream().use { load(it) }
    }

    assertEquals("CustomValue", properties.getProperty("custom.property"))
    assertEquals("https://api.example.com", properties.getProperty("api.url"))
}

This test loads the properties file as we would in production code. Then, the test verifies that the properties load correctly by comparing them to the expected values.

4. Conclusion

In this article, we explored several methods to retrieve custom properties defined in gradle.properties within a Kotlin application, using Gradle as the main entry point. We also discussed the importance of not directly accessing gradle.properties outside the build process.

We showed how to inject properties as system environment variables for tests. Furthermore, we generated a properties file for use in production code.

By applying these techniques, we can efficiently manage and access configuration values across different environments, ensuring that our Kotlin application remains well-configured and adaptable to various scenarios.


原始标题:Getting the Value of a Custom Property Defined in ‘gradle.properties’ in Kotlin