I would like to write a generic type-safe TestData...
# test
d
I would like to write a generic type-safe TestData class for JUnit parametrized tests. I imagine something like this:
Copy code
import org.junit.jupiter.params.provider.Arguments

data class TestData<G, E>(val testName: String, val given: G, val expected: E) {
    override fun toString() = testName
}

fun <G, E> List<TestData<G, E>>.asArguments() = map { Arguments.of(it) }

fun myTestMethodTestData() = listOf(
  TestData("test case 1", 1, "1"),
  TestData("test case 2", 2, "2"),
).asArguments()
This works fine but isn't type-safe, i.e. nothing prevents me from writing
Copy code
fun myTestMethodTestData() = listOf(
  TestData("test case 1", 1, "1"),
  TestData("test case 2", "2", 2),
).asArguments()
Is there any way how that can be achieved? At first I thought I could utilize
@NoInfer
to force the user to specify the type arguments explicitly, e.g.
asArguments<Int, String>()
, but of course that doesn't enforce anything about the types in the
TestData
class instance...
s
that doesn't answer your question, but if you're only passing only one value to
Arguments.of
and you later use method
myTestMethodTestData
for something like
@MethodSource
, you can omit
Arguments.of
wrapping and just return
List<TestData<G, E>>
in
myTestMethodTestData
, it would work the same way
And in case you want to provide ability of providing multiple arguments to test method, you can create a class which extends
Arguments
interface:
Copy code
data class ExampleTestDataWithMultipleArguments<A : Any, B : Any>(val first: A, val second: B) : Arguments {
     override fun get(): Array<Any> = arrayOf(first, second)
 }
you could then provide concrete typing for method in `@MethodSource`:
Copy code
@ParameterizedTest
@MethodSource("someTestDatas")
fun `example test`(first: Int, second: String) {

fun someTestDatas(): List<TestDataWithMultipleArguments<Int, String>> = listOf(
    TestDataWithMultipleArguments(1, "1"),
    TestDataWithMultipleArguments(2, "2"),
)
d
you can omit
Arguments.of
wrapping and
Thanks, I did not know that. That basically makes my original problem useless because
TestData
is meant to wrap all data for a single test case so its usage will always be
Copy code
fun someTestDatas(): List<TestData<Int, String>> = listOf(
    TestData(1, "1"),
    TestData(2, "2"),
)
Moreover, that explicit return type specification actually provides the type enforcement I was after.