kotlinx-resources
Kotlin Multiplatform (KMP) plugin and library for reading resources in tests.
It bridges the gap between different Kotlin Multiplatform targets, allowing you to access files from your resources folders in a single, consistent way.
Setup
Apply the plugin and add the library as a dependency in your build.gradle.kts:
plugins {
id("com.goncalossilva.resources") version "<version>"
}
// ...
kotlin {
sourceSets {
val commonTest by getting {
dependencies {
implementation("com.goncalossilva:resources:<version>")
}
}
}
}
Replace <version> with the latest version shown in the badge above.
Compatibility
Different Kotlin versions require different versions of the plugin/library:
| Kotlin | kotlinx-resources |
|---|---|
| 2.1 and above | 0.10 and above |
| 2.0 | 0.9 |
| 1.9 and below | 0.8 and below (plus k1 branch) |
Usage
To access a file in your tests:
- Place it in a
resourcesfolder. For example, insrc/commonTest/resources/to have it available in all targets, orsrc/jsTest/resources/to limit access to JS. - Instantiate a
Resourceclass with the path relative to that folder.
Basic Example
For a file located at src/commonTest/resources/data/example.json:
import com.goncalossilva.resources.Resource
class MyTest {
@Test
fun `example data exists`() {
val resource = Resource("data/example.json")
assertTrue(resource.exists())
}
@Test
fun `example data ends in a newline`() {
val content = Resource("data/example.json").readText()
assertTrue(content.endsWith("\n"))
}
}
API Overview
The Resource class provides a clean and simple API:
class Resource(path: String) {
// Checks if the resource exists at the given path.
fun exists(): Boolean
// Reads the entire resource content as a string decoded using the specified charset.
fun readText(charset: Charset = Charsets.UTF_8): String
// Reads the entire resource content as a byte array.
fun readBytes(): ByteArray
}
Example Project
Library tests use the library itself, so they serve as a practical example.
See ResourceTest for example usage, and resources-test/src/commonTest/resources for the associated folder structure for resources.
Caveats
Collisions
As a rule of thumb, place test files in src/commonTest/resources/. This avoids collisions entirely.
But if you want to override a common file, you can have a platform-specific version of it in the platform-specific source set (e.g., src/jvmTest/resources/). By default, Gradle will throw a "Entry (...) is a duplicate" error during the build process, prompting you to set a duplicateStrategy in your build.gradle.kts.
To have platform-specific resources override common ones, set the strategy to EXCLUDE:
tasks.withType<Copy>().configureEach {
if (name.contains("Test(?:Copy|Process)Resources$".toRegex())) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
}
Other DuplicatesStrategy options are available, but avoid INCLUDE, as the override behavior becomes inconsistent across platforms.
Browser limitations
In browser runtimes, readBytes() uses a synchronous XHR-based implementation to keep the API synchronous.
Some browser+tooling stacks can corrupt leading UTF-16 BOM bytes (0xFF 0xFE / 0xFE 0xFF), which makes
readText(Charsets.UTF_16) unreliable for UTF-16 files that include a BOM. Prefer Charsets.UTF_16LE /
Charsets.UTF_16BE (or files without a BOM) for browser tests.
Acknowledgements
This library is inspired by this gist by @dellisd.
License
Released under the MIT License.
