Reputation: 710
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
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
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
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