Kotest 用 java.lang.IllegalArgumentException 中断了 gradle 的 :test 任务:接收到未知 id 的测试失败事件
Kotest breaks gradle's :test task with java.lang.IllegalArgumentException: Received a failure event for test with unknown id
我开始使用 Kotest 在 Kotlin 中进行单元测试。我使用以下以某种方式与 Kotest 集成的技术:
- Kotest 本身
- 科特林/JVM
- Gradle
- 魅力
- 皮斯特
- IntelliJ IDEA 插件“Kotest”
在 gradle 中,我包含了以下依赖项:
io.kotest:kotest-runner-junit5:$kotest_version
: Kotest 框架
io.kotest:kotest-assertions-core:$kotest_version
:Kotest 核心 JVM 断言
io.kotest:kotest-property:$kotest_version
: 测试属性 测试
io.kotest:kotest-extensions-allure:$kotest_version
:Allure 的数据收集
io.kotest:kotest-plugins-pitest:$kotest_version
: Pitest 插件
现在的问题是,当我通过 gradle :test
任务 运行 进行测试时,出现以下异常:
java.lang.IllegalArgumentException: Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
每次测试中的未知 ID/注册 ID 都不同 运行。实际上有很多错误出现,但那个是最后一个出现的。下面是完整的 gradle 输出(缩短的内部调用):
Testing started at 18:39 ...
> Task :kaptGenerateStubsKotlin UP-TO-DATE
> Task :kaptKotlin UP-TO-DATE
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :kaptGenerateStubsTestKotlin UP-TO-DATE
> Task :kaptTestKotlin UP-TO-DATE
> Task :compileTestKotlin UP-TO-DATE
> Task :preTest
> Task :compileTestJava NO-SOURCE
> Task :processTestResources UP-TO-DATE
> Task :testClasses UP-TO-DATE
> Task :test
~~~ Kotest Configuration ~~~
-> Parallelization factor: 1
-> Default test timeout: 600000ms
-> Default test order: Sequential
-> Default isolation mode: SingleInstance
-> Global soft assertations: False
-> Write spec failure file: False
-> Fail on ignored tests: False
-> Spec execution order: SpecExecutionOrder
-> Extensions
- io.kotest.engine.extensions.SystemPropertyTagExtension
- io.kotest.core.extensions.RuntimeTagExtension
- io.kotest.engine.extensions.RuntimeTagExpressionExtension
-> Listeners
- io.kotest.extensions.allure.AllureTestReporter
- class io.kotest.engine.config.LoadConfigFromClasspathKt$toDetectedConfig$beforeAfterAllListener
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = FAILED, throwable = java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = FAILED, throwable = java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
java.lang.IllegalArgumentException: Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]' <19 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
> Task :test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 5s
10 actionable tasks: 2 executed, 8 up-to-date
可能相关的内容:
1。我在 build.gradle.kts
中使用自定义任务配置
我的 build.gradle.kts
文件的以下部分涵盖了所有与测试相关的内容,包括设置测试环境的任务和之后清理的第二个任务:
tasks.withType<Test> {
useJUnitPlatform()
}
allure {
autoconfigure = false
version = "2.13.6"
}
configure<PitestPluginExtension> {
testPlugin.set("Kotest")
targetClasses.set(listOf("com.example.*"))
}
val testDir1Path = "/src/test/resources/DirectoryTest"
val testDir2Path = "/src/test/resources/Create"
tasks.register("preTest") {
doLast {
mkdir(testDir1Path)
file("$testDir1Path/json00.json").apply { createNewFile() }.writeText("{ \"s\": \"s\", \"i\": 0, \"b\": true}")
file("$testDir1Path/json01.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json02.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json03.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json04.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json05.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json06.json").apply { createNewFile() }.writeText("{}")
}
}
tasks.register<Delete>("postTest") {
for (task in tasks.withType<Test>()) {
mustRunAfter(task)
}
delete(testDir1Path)
delete(testDir2Path)
delete("/src/test/resources/NonExistent") // might be created by :pitest
}
tasks.withType<Test>().configureEach {
dependsOn("preTest")
}
2。最先导致错误的测试套件
错误发生在我进行以下 Kotest 测试时 class,更准确地说,它发生在我尝试实施测试工厂并包含它之后:
class JSONFileTests : FunSpec({
test("Loading a file into the model JSONModel01 should work") {
shouldNotThrowAny {
JSONFile("$exists/json00.json", JSONModel01.serializer())
}.get() shouldBe JSONModel01("s", 0, true)
}
include("JSONModel01: ", echoTests(m1))
include("JSONModel02: ", echoTests(m2))
include("JSONModel03: ", echoTests(m3))
include("JSONModel04: ", echoTests(m4))
include("JSONModel05: ", echoTests(m5))
include("JSONModel06: ", echoTests(m6))
}) {
companion object {
private val m1 = JSONFile("$exists/json01.json", JSONModel01.serializer()) to JSONModel01()
private val m2 = JSONFile("$exists/json02.json", JSONModel02.serializer()) to JSONModel02()
private val m3 = JSONFile("$exists/json03.json", JSONModel03.serializer()) to JSONModel03()
private val m4 = JSONFile("$exists/json04.json", JSONModel04.serializer()) to JSONModel04()
private val m5 = JSONFile("$exists/json05.json", JSONModel05.serializer()) to JSONModel05()
private val m6 = JSONFile("$exists/json06.json", JSONModel06.serializer()) to JSONModel06()
private fun cleanupAll() {
m1.first.reload()
m2.first.reload()
m3.first.reload()
m4.first.reload()
m5.first.reload()
m6.first.reload()
}
private fun <T : JSONModelMarker> echoTests(model: Pair<JSONFile<T>, T>) = funSpec {
test("Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
}
}
所有 JSONModelXX
class 都是模型数据 class 仅用于测试。 JSONModelMarker
是所有 JSONModelXX
classes 实现的标记接口。JSONFile<T>
是我要测试的 class。
3。 IntelliJ 通知
我总是从 IntelliJ 收到“所有测试成功”的通知,但是当我查看测试工具 window 时,测试被标记为“失败”,因为 gradle 任务 :test
失败。我不知道这对问题有何影响。
4。我有时也会收到不同的异常
如果我 仅 运行 通过 IntelliJ 装订线图标在测试套件中进行第一个测试,我会得到一个不同的异常:java.lang.ExceptionInInitializerError
。我做了一些挖掘,发现用于读取 JSONFile<T>
class 中 JSON 文件内容的 Scanner
抛出 NoSuchElementException
因为(由于某种原因)文件在执行此测试期间 empty only。这很奇怪,因为我 build.gradle.kts
中的自定义 :preTest
任务实际上将一些内容写入每个文件,而当我查看文件 after[= 时,这些内容实际上就在那里121=] :preTest
或 :test
运行。这是完整的控制台输出:
java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at io.kotest.engine.launcher.ExecuteKt$execute.invokeSuspend(execute.kt:37)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlin.coroutines.ContinuationKt.startCoroutine(Continuation.kt:115)
at io.kotest.engine.launcher.ExecuteKt.future(execute.kt:89)
at io.kotest.engine.launcher.ExecuteKt.execute(execute.kt:34)
at io.kotest.engine.launcher.MainKt.main(main.kt:12)
Caused by: java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1478)
at com.example.core.common.JSONFile$Companion.readFile(JSONFile.kt:14)
at com.example.core.common.JSONFile$Companion.access$readFile(JSONFile.kt:11)
at com.example.core.common.JSONFile.<init>(JSONFile.kt:27)
at com.example.core.common.JSONFileTests.<clinit>(JSONFileTests.kt:24)
... 8 more
Process finished with exit code 0
[java.lang.ExceptionInInitializerError]
现在我不知道这是问题的一部分还是单独的问题,只是为了确定我想把它包括在这里。当我在 File->Settings->Build, Execution, Deployment->Build Tools->Gradle
中将测试 运行ner 切换到 IntelliJ IDEA 时,也会出现同样的问题
就是这样!现在我的问题是:什么 导致了这个错误,我该如何解决?
运行
- kotlin/JVM 1.4.10
- kotest-运行ner-junit5 4.3.1
- kotest-assertions-core 4.3.1
- kotest-属性 4.3.1
- kotest-extensions-allure 4.3.1
- kotest-plugins-pitest 4.3.1
- gradle6.7
- 诱惑 2.13.6
- allure gradle 插件 2.8.1
- pitest gradle 插件 1.5.1
- intellij IDEA 旗舰版 2020.2
- kotest IntelliJ 插件 1.1.20-IC-2020.2
- openJDK 11.0.2
看来我找到了解决办法。
问题似乎是 Kotest(以及后来的 JUnit)想要唯一的测试,这意味着唯一的测试名称。通常,这些问题会被 Kotest IntelliJ 插件标记出来。但是如果你使用测试工厂,事情就有点不透明了。我假设 include(prefix, testFactory)
将 prefix
添加到测试名称,但事实并非如此。这意味着工厂方法
private fun <T : JSONModelMarker> echoTests(model: Pair<JSONFile<T>, T>) = funSpec {
test("Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
实际上每次调用时都会创建一个具有固定标识符的测试。现在,当我通过 include()
多次包含这个测试工厂时,我实际上创建了重复的测试,然后使测试任务崩溃。为了解决这个问题,我刚刚实现了一个功能来替换测试名称,如下所示:
private fun <T : JSONModelMarker> echoTests(name: String, model: Pair<JSONFile<T>, T>) = funSpec {
test("$name: Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
现在,当我调用 include()
方法时,我省略了前缀(因为它不相关)并向工厂方法调用添加了一个唯一名称(以前是前缀):
include(echoTests("JSONModel01", m1))
我这样做之后,错误就没有再出现了。
我开始使用 Kotest 在 Kotlin 中进行单元测试。我使用以下以某种方式与 Kotest 集成的技术:
- Kotest 本身
- 科特林/JVM
- Gradle
- 魅力
- 皮斯特
- IntelliJ IDEA 插件“Kotest”
在 gradle 中,我包含了以下依赖项:
io.kotest:kotest-runner-junit5:$kotest_version
: Kotest 框架io.kotest:kotest-assertions-core:$kotest_version
:Kotest 核心 JVM 断言io.kotest:kotest-property:$kotest_version
: 测试属性 测试io.kotest:kotest-extensions-allure:$kotest_version
:Allure 的数据收集
io.kotest:kotest-plugins-pitest:$kotest_version
: Pitest 插件
现在的问题是,当我通过 gradle :test
任务 运行 进行测试时,出现以下异常:
java.lang.IllegalArgumentException: Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
每次测试中的未知 ID/注册 ID 都不同 运行。实际上有很多错误出现,但那个是最后一个出现的。下面是完整的 gradle 输出(缩短的内部调用):
Testing started at 18:39 ...
> Task :kaptGenerateStubsKotlin UP-TO-DATE
> Task :kaptKotlin UP-TO-DATE
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :kaptGenerateStubsTestKotlin UP-TO-DATE
> Task :kaptTestKotlin UP-TO-DATE
> Task :compileTestKotlin UP-TO-DATE
> Task :preTest
> Task :compileTestJava NO-SOURCE
> Task :processTestResources UP-TO-DATE
> Task :testClasses UP-TO-DATE
> Task :test
~~~ Kotest Configuration ~~~
-> Parallelization factor: 1
-> Default test timeout: 600000ms
-> Default test order: Sequential
-> Default isolation mode: SingleInstance
-> Global soft assertations: False
-> Write spec failure file: False
-> Fail on ignored tests: False
-> Spec execution order: SpecExecutionOrder
-> Extensions
- io.kotest.engine.extensions.SystemPropertyTagExtension
- io.kotest.core.extensions.RuntimeTagExtension
- io.kotest.engine.extensions.RuntimeTagExpressionExtension
-> Listeners
- io.kotest.extensions.allure.AllureTestReporter
- class io.kotest.engine.config.LoadConfigFromClasspathKt$toDetectedConfig$beforeAfterAllListener
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = FAILED, throwable = java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = FAILED, throwable = java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Nov. 04, 2020 6:39:48 NACHM. org.junit.platform.launcher.core.TestExecutionListenerRegistry lambda$notifyEach
WARNING: TestExecutionListener [org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestExecutionListener] threw exception for method: executionFinished(TestIdentifier [uniqueId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]/[test:Writing to and reading from file should result in the original value]', parentId = '[engine:kotest]/[spec:com.example.core.common.JSONFileTests]', displayName = 'Writing to and reading from file should result in the original value', legacyReportingName = 'Writing to and reading from file should result in the original value', source = FileSource [file = D:\dev\Minecraft Server Watcher\msw-server\JSONFileTests.kt, filePosition = FilePosition [line = 40, column = -1]], tags = [], type = TEST], TestExecutionResult [status = SUCCESSFUL, throwable = null])
java.lang.AssertionError <3 internal calls>
at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source) <11 internal calls>
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) <17 internal calls>
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) <5 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
java.lang.IllegalArgumentException: Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]' <19 internal calls>
at java.base/java.lang.Thread.run(Thread.java:834)
> Task :test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> Received a failure event for test with unknown id '2.27'. Registered test ids: '[2.1, :test, 2.25]'
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 5s
10 actionable tasks: 2 executed, 8 up-to-date
可能相关的内容:
1。我在 build.gradle.kts
中使用自定义任务配置
我的 build.gradle.kts
文件的以下部分涵盖了所有与测试相关的内容,包括设置测试环境的任务和之后清理的第二个任务:
tasks.withType<Test> {
useJUnitPlatform()
}
allure {
autoconfigure = false
version = "2.13.6"
}
configure<PitestPluginExtension> {
testPlugin.set("Kotest")
targetClasses.set(listOf("com.example.*"))
}
val testDir1Path = "/src/test/resources/DirectoryTest"
val testDir2Path = "/src/test/resources/Create"
tasks.register("preTest") {
doLast {
mkdir(testDir1Path)
file("$testDir1Path/json00.json").apply { createNewFile() }.writeText("{ \"s\": \"s\", \"i\": 0, \"b\": true}")
file("$testDir1Path/json01.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json02.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json03.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json04.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json05.json").apply { createNewFile() }.writeText("{}")
file("$testDir1Path/json06.json").apply { createNewFile() }.writeText("{}")
}
}
tasks.register<Delete>("postTest") {
for (task in tasks.withType<Test>()) {
mustRunAfter(task)
}
delete(testDir1Path)
delete(testDir2Path)
delete("/src/test/resources/NonExistent") // might be created by :pitest
}
tasks.withType<Test>().configureEach {
dependsOn("preTest")
}
2。最先导致错误的测试套件
错误发生在我进行以下 Kotest 测试时 class,更准确地说,它发生在我尝试实施测试工厂并包含它之后:
class JSONFileTests : FunSpec({
test("Loading a file into the model JSONModel01 should work") {
shouldNotThrowAny {
JSONFile("$exists/json00.json", JSONModel01.serializer())
}.get() shouldBe JSONModel01("s", 0, true)
}
include("JSONModel01: ", echoTests(m1))
include("JSONModel02: ", echoTests(m2))
include("JSONModel03: ", echoTests(m3))
include("JSONModel04: ", echoTests(m4))
include("JSONModel05: ", echoTests(m5))
include("JSONModel06: ", echoTests(m6))
}) {
companion object {
private val m1 = JSONFile("$exists/json01.json", JSONModel01.serializer()) to JSONModel01()
private val m2 = JSONFile("$exists/json02.json", JSONModel02.serializer()) to JSONModel02()
private val m3 = JSONFile("$exists/json03.json", JSONModel03.serializer()) to JSONModel03()
private val m4 = JSONFile("$exists/json04.json", JSONModel04.serializer()) to JSONModel04()
private val m5 = JSONFile("$exists/json05.json", JSONModel05.serializer()) to JSONModel05()
private val m6 = JSONFile("$exists/json06.json", JSONModel06.serializer()) to JSONModel06()
private fun cleanupAll() {
m1.first.reload()
m2.first.reload()
m3.first.reload()
m4.first.reload()
m5.first.reload()
m6.first.reload()
}
private fun <T : JSONModelMarker> echoTests(model: Pair<JSONFile<T>, T>) = funSpec {
test("Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
}
}
所有 JSONModelXX
class 都是模型数据 class 仅用于测试。 JSONModelMarker
是所有 JSONModelXX
classes 实现的标记接口。JSONFile<T>
是我要测试的 class。
3。 IntelliJ 通知
我总是从 IntelliJ 收到“所有测试成功”的通知,但是当我查看测试工具 window 时,测试被标记为“失败”,因为 gradle 任务 :test
失败。我不知道这对问题有何影响。
4。我有时也会收到不同的异常
如果我 仅 运行 通过 IntelliJ 装订线图标在测试套件中进行第一个测试,我会得到一个不同的异常:java.lang.ExceptionInInitializerError
。我做了一些挖掘,发现用于读取 JSONFile<T>
class 中 JSON 文件内容的 Scanner
抛出 NoSuchElementException
因为(由于某种原因)文件在执行此测试期间 empty only。这很奇怪,因为我 build.gradle.kts
中的自定义 :preTest
任务实际上将一些内容写入每个文件,而当我查看文件 after[= 时,这些内容实际上就在那里121=] :preTest
或 :test
运行。这是完整的控制台输出:
java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at io.kotest.engine.launcher.ExecuteKt$execute.invokeSuspend(execute.kt:37)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlin.coroutines.ContinuationKt.startCoroutine(Continuation.kt:115)
at io.kotest.engine.launcher.ExecuteKt.future(execute.kt:89)
at io.kotest.engine.launcher.ExecuteKt.execute(execute.kt:34)
at io.kotest.engine.launcher.MainKt.main(main.kt:12)
Caused by: java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1478)
at com.example.core.common.JSONFile$Companion.readFile(JSONFile.kt:14)
at com.example.core.common.JSONFile$Companion.access$readFile(JSONFile.kt:11)
at com.example.core.common.JSONFile.<init>(JSONFile.kt:27)
at com.example.core.common.JSONFileTests.<clinit>(JSONFileTests.kt:24)
... 8 more
Process finished with exit code 0
[java.lang.ExceptionInInitializerError]
现在我不知道这是问题的一部分还是单独的问题,只是为了确定我想把它包括在这里。当我在 File->Settings->Build, Execution, Deployment->Build Tools->Gradle
中将测试 运行ner 切换到 IntelliJ IDEA 时,也会出现同样的问题就是这样!现在我的问题是:什么 导致了这个错误,我该如何解决?
运行
- kotlin/JVM 1.4.10
- kotest-运行ner-junit5 4.3.1
- kotest-assertions-core 4.3.1
- kotest-属性 4.3.1
- kotest-extensions-allure 4.3.1
- kotest-plugins-pitest 4.3.1
- gradle6.7
- 诱惑 2.13.6
- allure gradle 插件 2.8.1
- pitest gradle 插件 1.5.1
- intellij IDEA 旗舰版 2020.2
- kotest IntelliJ 插件 1.1.20-IC-2020.2
- openJDK 11.0.2
看来我找到了解决办法。
问题似乎是 Kotest(以及后来的 JUnit)想要唯一的测试,这意味着唯一的测试名称。通常,这些问题会被 Kotest IntelliJ 插件标记出来。但是如果你使用测试工厂,事情就有点不透明了。我假设 include(prefix, testFactory)
将 prefix
添加到测试名称,但事实并非如此。这意味着工厂方法
private fun <T : JSONModelMarker> echoTests(model: Pair<JSONFile<T>, T>) = funSpec {
test("Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
实际上每次调用时都会创建一个具有固定标识符的测试。现在,当我通过 include()
多次包含这个测试工厂时,我实际上创建了重复的测试,然后使测试任务崩溃。为了解决这个问题,我刚刚实现了一个功能来替换测试名称,如下所示:
private fun <T : JSONModelMarker> echoTests(name: String, model: Pair<JSONFile<T>, T>) = funSpec {
test("$name: Writing to and reading from file should result in the original value") {
model.first.apply { setAndCommit(model.second) }.get() shouldBe model.second
model.first.reload()
}
}
现在,当我调用 include()
方法时,我省略了前缀(因为它不相关)并向工厂方法调用添加了一个唯一名称(以前是前缀):
include(echoTests("JSONModel01", m1))
我这样做之后,错误就没有再出现了。