JUnit 5 参数化测试 - 'Cannot invoke non-static method' in @MethodSource with Kotlin
JUnit 5 Parameterized Test - 'Cannot invoke non-static method' in @MethodSource with Kotlin
期待
将标准 JUnit 5 测试转换为参数化测试,以便使用 Kotlin 中的 @ParamterizedTest
和 @MethodSource
注释遍历测试用例流。
观察
@MethodSource
无法访问数据流。这似乎是此注释的一个问题,因为 @ValueSource(strings = ["SF", "NYC"])
按预期遍历静态定义的选项。
错误:
PreconditionViolationException: Cannot invoke non-static method {someMethodName} on a null target.
实施
参数化测试设置为传递数据流 类 类似于 Phillip Hauer 在 Data Classes for Parameterized Tests.
中概述的设置
代码
build.gradle (:SomeProject)
dependencies {
...
classpath("de.mannodermaus.gradle.plugins:android-junit5:$junit5_version")
}
build.gradle (:someModule)
apply plugin: "de.mannodermaus.android-junit5"
android {
...
compileOptions.targetCompatibility = JavaVersion.VERSION_1_8
kotlinOptions.jvmTarget = "1.8"
}
dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.6.2"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.6.2"
}
SomeTest.kt
class SomeTest {
private val testDispatcher = TestCoroutineDispatcher()
private fun someDataStates() = Stream.of(
// Kotlin data class
TestState("123"),
TestState("345")
)
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
}
搭建环境
- Android Studio 4.0
- 构建 #AI-193.6911.18.40.6514223,构建于 2020 年 5 月 20 日
- 运行时版本:1.8.0_242-release-1644-b3-6222593 x86_64
- VM:JetBrains 的 OpenJDK 64 位服务器 VM s.r.o
- macOS 10.15.5
- GC: ParNew, ConcurrentMarkSweep
- 内存:1979M
- 核心数:16
- 注册表:ide.new.welcome.screen.force=true
- 非捆绑插件:cn.wjdghd.unique.plugin.id、com.android.tool.sizereduction.plugin、com.developerphil.adbidea、com.thoughtworks.gauge、mobi.hsz.idea.gitignore
尝试过的解决方案
1。将测试用例数据状态重构为顶级函数。
TestCases.kt
fun someDataStates() = Stream.of(
TestState("123"),
TestState("345")
)
SomeTest.kt
private fun SomeDataStates() = someDataStates()
@ParameterizedTest
@MethodSource("SomeDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
2。将测试用例数据状态重构为 List
类型的顶级函数,而不是 Stream
.
fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
完整的错误日志
org.junit.platform.commons.PreconditionViolationException: Cannot invoke non-static method [private final {someMethodName} on a null target.
at org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:296)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:682)
at org.junit.jupiter.params.provider.MethodArgumentsProvider.lambda$provideArguments(MethodArgumentsProvider.java:46)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:106)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Suppressed: org.junit.platform.commons.PreconditionViolationException: Configuration error: You must configure at least one set of arguments for this @ParameterizedTest
at org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:281)
at org.junit.jupiter.params.ParameterizedTestExtension.lambda$provideTestTemplateInvocationContexts(ParameterizedTestExtension.java:90)
at java.util.stream.AbstractPipeline.close(AbstractPipeline.java:323)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:279)
... 49 more
Process finished with exit code 255
我猜你错过了告诉 JUnit 实例化你的测试 class 一次的信息,如下所示:
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
@TestInstance(PER_CLASS) // <--- This one will do the trick
class SomeTest {
private val testDispatcher = TestCoroutineDispatcher()
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
private fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
}
使用 @TestInstance(PER_CLASS)
,您可能会遇到麻烦,例如,当您尝试验证某个函数已被 mockito
或 mockk
调用 X 次时。您必须汇总所有来电。
在这种情况下,使用 @JvmStatic
:
class SomeTest {
companion object{
@JvmStatic
private fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
}
private val testDispatcher = TestCoroutineDispatcher()
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
}
编辑 27/08/2021: 自最新版本的 kotlin(使用 1.5.21 测试)以来,请勿将 @JvmStatic 方法设置为 private
或它会再次以 PreconditionViolationException
结束
如果由于某种原因您不能使用 @TestInstance(PER_CLASS)
注释,您可以在测试方法上使用 @TestFactory
注释而不是 @ParameterizedTest
注释。
@TestFactory
Stream<DynamicTest> someTest() {
return someDataStates().map(testState -> DynamicTest.dynamicTest(testState.getName(), () -> someTest0(testState)));
}
private void someTest0(TestState testState) {
// Test state here.
}
private Stream<TestState> someDataStates() {
return Stream.of(
new TestState("123"),
new TestState("345")
);
}
期待
将标准 JUnit 5 测试转换为参数化测试,以便使用 Kotlin 中的 @ParamterizedTest
和 @MethodSource
注释遍历测试用例流。
观察
@MethodSource
无法访问数据流。这似乎是此注释的一个问题,因为 @ValueSource(strings = ["SF", "NYC"])
按预期遍历静态定义的选项。
错误:
PreconditionViolationException: Cannot invoke non-static method {someMethodName} on a null target.
实施
参数化测试设置为传递数据流 类 类似于 Phillip Hauer 在 Data Classes for Parameterized Tests.
中概述的设置代码
build.gradle (:SomeProject)
dependencies {
...
classpath("de.mannodermaus.gradle.plugins:android-junit5:$junit5_version")
}
build.gradle (:someModule)
apply plugin: "de.mannodermaus.android-junit5"
android {
...
compileOptions.targetCompatibility = JavaVersion.VERSION_1_8
kotlinOptions.jvmTarget = "1.8"
}
dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.6.2"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.6.2"
}
SomeTest.kt
class SomeTest {
private val testDispatcher = TestCoroutineDispatcher()
private fun someDataStates() = Stream.of(
// Kotlin data class
TestState("123"),
TestState("345")
)
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
}
搭建环境
- Android Studio 4.0
- 构建 #AI-193.6911.18.40.6514223,构建于 2020 年 5 月 20 日
- 运行时版本:1.8.0_242-release-1644-b3-6222593 x86_64
- VM:JetBrains 的 OpenJDK 64 位服务器 VM s.r.o
- macOS 10.15.5
- GC: ParNew, ConcurrentMarkSweep
- 内存:1979M
- 核心数:16
- 注册表:ide.new.welcome.screen.force=true
- 非捆绑插件:cn.wjdghd.unique.plugin.id、com.android.tool.sizereduction.plugin、com.developerphil.adbidea、com.thoughtworks.gauge、mobi.hsz.idea.gitignore
尝试过的解决方案
1。将测试用例数据状态重构为顶级函数。
TestCases.kt
fun someDataStates() = Stream.of(
TestState("123"),
TestState("345")
)
SomeTest.kt
private fun SomeDataStates() = someDataStates()
@ParameterizedTest
@MethodSource("SomeDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
2。将测试用例数据状态重构为 List
类型的顶级函数,而不是 Stream
.
fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
完整的错误日志
org.junit.platform.commons.PreconditionViolationException: Cannot invoke non-static method [private final {someMethodName} on a null target.
at org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:296) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:682) at org.junit.jupiter.params.provider.MethodArgumentsProvider.lambda$provideArguments(MethodArgumentsProvider.java:46) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:106) at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:135) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.util.ArrayList.forEach(ArrayList.java:1257) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.util.ArrayList.forEach(ArrayList.java:1257) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248) at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute(DefaultLauncher.java:211) at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58) Suppressed: org.junit.platform.commons.PreconditionViolationException: Configuration error: You must configure at least one set of arguments for this @ParameterizedTest at org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:281) at org.junit.jupiter.params.ParameterizedTestExtension.lambda$provideTestTemplateInvocationContexts(ParameterizedTestExtension.java:90) at java.util.stream.AbstractPipeline.close(AbstractPipeline.java:323) at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:279) ... 49 more
Process finished with exit code 255
我猜你错过了告诉 JUnit 实例化你的测试 class 一次的信息,如下所示:
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
@TestInstance(PER_CLASS) // <--- This one will do the trick
class SomeTest {
private val testDispatcher = TestCoroutineDispatcher()
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
private fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
}
使用 @TestInstance(PER_CLASS)
,您可能会遇到麻烦,例如,当您尝试验证某个函数已被 mockito
或 mockk
调用 X 次时。您必须汇总所有来电。
在这种情况下,使用 @JvmStatic
:
class SomeTest {
companion object{
@JvmStatic
private fun someDataStates() = listOf(
TestState("123"),
TestState("345")
)
}
private val testDispatcher = TestCoroutineDispatcher()
@ParameterizedTest
@MethodSource("someDataStates")
fun someTest(testState: TestState) = testDispatcher.runBlockingTest {
// Test state here.
...
}
}
编辑 27/08/2021: 自最新版本的 kotlin(使用 1.5.21 测试)以来,请勿将 @JvmStatic 方法设置为 private
或它会再次以 PreconditionViolationException
如果由于某种原因您不能使用 @TestInstance(PER_CLASS)
注释,您可以在测试方法上使用 @TestFactory
注释而不是 @ParameterizedTest
注释。
@TestFactory
Stream<DynamicTest> someTest() {
return someDataStates().map(testState -> DynamicTest.dynamicTest(testState.getName(), () -> someTest0(testState)));
}
private void someTest0(TestState testState) {
// Test state here.
}
private Stream<TestState> someDataStates() {
return Stream.of(
new TestState("123"),
new TestState("345")
);
}