Search code examples
kotlinjunit5parametrized-testing

Use pure Kotlin function as Junit5 methodsource


I am curious if in the Kotlin, in the parameterized tests in Junit5, i can use the method outside the class as the @MethodSource.

I know about 2 ways to use @MethodSource in Kotlin - companion object and @TestInstance(TestInstance.Lifecycle.PER_CLASS). I wonder if it can be done in a different way, for example by declaring a method outside the class and using some annotation? I tried to do it this way, but it does not work, I wonder if something similar can be done.

class GenerationStatusTest {

    @ParameterizedTest
    @MethodSource("provideStatusesToTest")
    internal fun shouldStatusesHaveExpectedAbilities(generationStatus: GenerationStatus, assertions:(GenerationStatus)->Unit) {
        assertions(generationStatus)
    }
}

fun provideStatusesToTest(): Stream<Arguments> {
    return Stream.of(
            Arguments.of(WAITING, canDoNothing),
            Arguments.of(PROCESSING, canDoNothing)
    )
}
org.junit.platform.commons.JUnitException: Could not find factory method [provideStatusesToTest] in class [com.test.enums.GenerationStatusTest]
    at org.junit.jupiter.params.provider.MethodArgumentsProvider.lambda$getMethod$4(MethodArgumentsProvider.java:83)

Solution

  • JUnit documentation says

    An external, static factory method can be referenced by providing its fully qualified method name as demonstrated in the following example.

    And Kotlin documentation says

    All the functions and properties declared in a file app.kt inside a package org.example, including extension functions, are compiled into static methods of a Java class named org.example.AppKt.

    So if the package name is com.test.enums (from the error message), and your file name is GenerationStatusTest.kt, then the generated class containing provideStatusesToTest is com.test.GenerationStatusTestKt, so the annotation you need is

    @MethodSource("com.test.enums.GenerationStatusTestKt#provideStatusesToTest")