Gradle 添加koin测试依赖的问题

Gradle problems of adding koin test dependencies

我是 gradle 的初学者,想在我的 Kotlin 项目中使用 koin

但是,我收到以下错误

Execution failed for task ':compileTestKotlin'.
> Error while evaluating property 'filteredArgumentsMap' of task ':compileTestKotlin'
   > Could not resolve all files for configuration ':testCompileClasspath'.
      > Could not resolve org.jetbrains.kotlin:kotlin-test-junit5:1.6.20.
        Required by:
            project : > org.jetbrains.kotlin:kotlin-test:1.6.20
         > Module 'org.jetbrains.kotlin:kotlin-test-junit5' has been rejected:
              Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.20' also provided by [org.jetbrains.kotlin:kotlin-test-junit:1.6.10(junitApi)]
      > Could not resolve org.jetbrains.kotlin:kotlin-test-junit:1.6.10.
        Required by:
            project : > io.insert-koin:koin-test:3.2.0-beta-1 > io.insert-koin:koin-test-jvm:3.2.0-beta-1
         > Module 'org.jetbrains.kotlin:kotlin-test-junit' has been rejected:
              Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.10' also provided by [org.jetbrains.kotlin:kotlin-test-junit5:1.6.20(junit5Api)]```

这是我的 gradle.build.kts 文件

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val koinVersion = "3.2.0-beta-1"

plugins {
    kotlin("jvm") version "1.6.20"
    kotlin("plugin.serialization") version "1.6.10"
    application
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
    implementation("io.insert-koin:koin-core:$koinVersion")
    testImplementation("io.insert-koin:koin-test:$koinVersion")
    testImplementation("io.insert-koin:koin-test-junit5:$koinVersion")
    testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

application {
    mainClass.set("MainKt")
}

好像有3个问题

正如我在评论中提到的,Kotlin JVM 和序列化插件的版本不匹配。这些应该始终相同!

plugins {
  kotlin("jvm") version "1.6.21"
  kotlin("plugin.serialization") version "1.6.21"
  application
}

但是,正如您发现的那样,它仍然不起作用。有一条较大的错误消息,包含三个错误。

  1. Could not resolve io.insert-koin:koin-test-junit5:3.2.0-beta-1
  2. Could not resolve org.jetbrains.kotlin:kotlin-test-junit5:1.6.21
  3. Could not resolve org.jetbrains.kotlin:kotlin-test-junit:1.6.10

让我们来看看它们 one-by-one

Java 11 个库,Java 8 个项目

这是 Gradle 给出的第一次失败的原因:

Could not resolve io.insert-koin:koin-test-junit5:3.2.0-beta-1.

No matching variant of io.insert-koin:koin-test-junit5:3.2.0-beta-1 was found. The consumer was configured to find an API of a library compatible with Java 8, preferably in the form of class files, preferably optimized for standard JVMs, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but

  • Incompatible because this component declares a component compatible with Java 11 and the consumer needed a component compatible with Java 8

组件 koin-test-junit5 仅与 Java 11 兼容,但您的项目需要 Java 8 (kotlinOptions.jvmTarget = "1.8")。

让我们先解决这个问题,using Gradle Toolchain

tasks.withType<KotlinCompile>().configureEach {
  kotlinOptions.jvmTarget = "11"
}

kotlin {
  jvmToolchain {
    (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(11))
  }
}

这解决了 Java 版本 mis-match,并留下了两个错误。

功能冲突 - 库不兼容

Cannot select module with conflict on capability

Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.10' also provided by [org.jetbrains.kotlin:kotlin-test-junit:1.6.10(junitApi)]

Cannot select module with conflict on capability 'org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.10' also provided by [org.jetbrains.kotlin:kotlin-test-junit5:1.6.10(junit5Api)]

理解这一点需要对 Gradle 如何选择版本有相当多的了解。

tl;dr:org.jetbrains.kotlin:kotlin-test-junitorg.jetbrains.kotlin:kotlin-test-junit5 不兼容。您只能使用一个或另一个 - 不能同时使用

我不太明白 Koin 需要什么才能发挥最大作用。看起来它对 JUnit5 有很强的依赖性,所以你必须使用这些依赖性,并且不能使用 kotlin("test")

dependencies {
  implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
  implementation("io.insert-koin:koin-core:$koinVersion")
  testImplementation("io.insert-koin:koin-test:$koinVersion")
  testImplementation("io.insert-koin:koin-test-junit5:$koinVersion")
  testImplementation("com.willowtreeapps.assertk:assertk:0.25")
  testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")


// incompatible with JUnit 5, which I think is required by Koin?
// testImplementation(kotlin("test")) 
}

说明

简而言之,当您使用Gradle建库时,您可以声明'attributes'。它们是 free-form 字符串,所以它们真的可以是任何东西。他们描述了诸如“这个库需要 Java 11”或“这是测试覆盖率数据”之类的东西。

一些属性对于 Gradle 解决项目的依赖关系很重要。您最初得到的错误是由一个这样的属性引起的:'capability'。它描述了库生成的 Maven 坐标。

在 Maven 坐标的情况下,如果它们发生冲突,那么 Gradle 不知道该怎么办,并抛出错误。由用户来修复它。 There's a lot of Gradle docs about conflict resolution,但通常最简单的答案是删除所有冲突的依赖项。

capabilities 的有趣之处在于,因为它只是一个字符串,所以您可以向其中添加任何内容。 org.jetbrains.kotlin:kotlin-test-junit5org.jetbrains.kotlin:kotlin-test-junit 的作者所做的是赋予他们相同的能力

org.jetbrains.kotlin:kotlin-test-framework-impl:1.6.10

如果你search for this library你会发现它不存在。那是因为能力完全是人为的!作者自己编的,特意是Gradle会报错,要用户自行修复。

这就是解决方法:选择 kotlin-test-junitkotlin-test-junit5,因为你不能同时拥有两者。

我认为 org.jetbrains.kotlin:kotlin-test-junit5 存在依赖性问题。

我也遇到了同样的问题,所以我尝试了多种解决方案,但都失败了。

我意识到,当只为 kotlin-test-junit5 添加依赖项时,kotlin-test-junit 也被添加到外部库中。

这是适合我的解决方案。

我首先将此行添加到 gradle 以启用 useJunitPlatform()

tasks.withType<Test> {
    useJUnitPlatform()
}

之后,我将 kotlin-test-junit 从每个这样的引用中排除,

    testImplementation("io.ktor:ktor-server-tests-jvm:$ktorVersion")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion") {
        exclude(group = "org.jetbrains.kotlin", module = "kotlin-test-junit")
    }

    // Dependency Injection
    val koinVersion: String by project
    implementation("io.insert-koin", "koin-ktor", koinVersion)
    implementation("io.insert-koin", "koin-logger-slf4j", koinVersion)
    testImplementation("io.insert-koin", "koin-test-junit5", koinVersion) {
        exclude(group = "org.jetbrains.kotlin", module = "kotlin-test-junit")
    }

之后,junit5 测试运行完美。