ssc327
ssc327

Reputation: 710

Junit5 Duplicated parameter in parameterized test

I have a function that takes in two objects and returns the "largest" one. For the purpose of this question the determination of "largest" is not important. I have a parameterized test that looks like the following:

@ParameterizedTest()
@MethodSource
void testGetLargest(Widget widget1, Widget widget2, Widget expectedLargestWidget) {
   var largestWidget = service.getLargestWidget(widget1, widget2);

   assertEquals(expectedLargestWidget, largestWidget);
}

private static Stream<Arguments> testGetLargest() {
    return Stream.of(
            Arguments.of(
                    Widget.builder().field1("something").field2("something else").build(),
                    Widget.builder().field1("second something").field2("second something else").build(),
                    **not sure what to put here**),
                    ...

As you can see, the third parameter for the test should be the same as one of the first two. While I could copy the code and make a third argument which is the same as one of the first two, this feels messy.

Is there a way to either build the arguments in a way that I can pass the same object as one of the first two as the third parameter?

Or that in my test, I can reference one of the existing params as the third one? I have considered having the third param be an int that represents index for one of the first two and then using reflection but this also feels heavy.

Upvotes: 1

Views: 280

Answers (3)

Qiu Zhou
Qiu Zhou

Reputation: 1275

I think you kind of over thought it, since you know which one should be the largest one, you can always put the expected one as the first parameter, then compare largestWidget with it, you would only need two parameters :

@ParameterizedTest()
@MethodSource
void testGetLargest(Widget widget1, Widget widget2) {
   var largestWidget = service.getLargestWidget(widget1, widget2);

   assertEquals(widget1, largestWidget);
}

Upvotes: 1

ssc327
ssc327

Reputation: 710

This seems to be a case where a fresh look the next day lead to a very obvious answer. I updated my methodSource function to first build the objects and then pass references to them and this allowed me to reuse the reference to the largest widget.

private static Stream<Arguments> testGetLargest() {
   Widget widget1 = Widget.builder().field1("something").field2("something else").build();
   Widget widget2 = Widget.builder().field1("second something").field2("second something else").build();
    return Stream.of(
            Arguments.of(
                    widget1,
                    widget2,
                    widget1),
                    ...

Upvotes: 0

Elmar Brauch
Elmar Brauch

Reputation: 1376

Instead of @MethodSource you can try @CsvSource.
I did this when I needed 3 Integer parameters in one parameterized test.
Here is the signature of my test method:

@ParameterizedTest
@CsvSource("300,10,", "150,5,", "90,9,0", "100,0,10")
fun totalScoreTests(result: Int, firstThrow: Int, secondThrow: Int?)

It is Kotlin instead of Java, but JUnit 5 is usable in both languages.
You can find my full example in this blog post, if you search for "GameTest":
https://agile-coding.blogspot.com/2021/06/clean-code-dojo.html

Upvotes: 0

Related Questions