Skip to content

Commit 078661e

Browse files
authored
Supply invocation index for @ParameterizedTest to test author (#3085)
Resolves #3085 by adding `ArgumentsAccessor.getInvocationIndex()`
1 parent 8617495 commit 078661e

File tree

10 files changed

+75
-49
lines changed

10 files changed

+75
-49
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ repository on GitHub.
4242

4343
==== New Features and Improvements
4444

45-
*
45+
* New `ArgumentsAccessor.getInvocationIndex` method to supply index of a `@ParameterizedTest` invocation.
4646

4747

4848
[[release-notes-5.10.0-M1-junit-vintage]]

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContex
9292
.map(arguments -> consumedArguments(arguments, methodContext))
9393
.map(arguments -> {
9494
invocationCount.incrementAndGet();
95-
return createInvocationContext(formatter, methodContext, arguments);
95+
return createInvocationContext(formatter, methodContext, arguments, invocationCount.intValue());
9696
})
9797
.onClose(() ->
9898
Preconditions.condition(invocationCount.get() > 0,
@@ -122,8 +122,8 @@ private ExtensionContext.Store getStore(ExtensionContext context) {
122122
}
123123

124124
private TestTemplateInvocationContext createInvocationContext(ParameterizedTestNameFormatter formatter,
125-
ParameterizedTestMethodContext methodContext, Object[] arguments) {
126-
return new ParameterizedTestInvocationContext(formatter, methodContext, arguments);
125+
ParameterizedTestMethodContext methodContext, Object[] arguments, int invocationIndex) {
126+
return new ParameterizedTestInvocationContext(formatter, methodContext, arguments, invocationIndex);
127127
}
128128

129129
private ParameterizedTestNameFormatter createNameFormatter(ExtensionContext extensionContext, Method templateMethod,

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestInvocationContext.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ class ParameterizedTestInvocationContext implements TestTemplateInvocationContex
2525
private final ParameterizedTestNameFormatter formatter;
2626
private final ParameterizedTestMethodContext methodContext;
2727
private final Object[] arguments;
28+
private final int invocationIndex;
2829

2930
ParameterizedTestInvocationContext(ParameterizedTestNameFormatter formatter,
30-
ParameterizedTestMethodContext methodContext, Object[] arguments) {
31+
ParameterizedTestMethodContext methodContext, Object[] arguments, int invocationIndex) {
3132
this.formatter = formatter;
3233
this.methodContext = methodContext;
3334
this.arguments = arguments;
35+
this.invocationIndex = invocationIndex;
3436
}
3537

3638
@Override
@@ -40,7 +42,8 @@ public String getDisplayName(int invocationIndex) {
4042

4143
@Override
4244
public List<Extension> getAdditionalExtensions() {
43-
return singletonList(new ParameterizedTestParameterResolver(this.methodContext, this.arguments));
45+
return singletonList(
46+
new ParameterizedTestParameterResolver(this.methodContext, this.arguments, this.invocationIndex));
4447
}
4548

4649
}

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestMethodContext.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ int indexOfFirstAggregator() {
161161
* Resolve the parameter for the supplied context using the supplied
162162
* arguments.
163163
*/
164-
Object resolve(ParameterContext parameterContext, Object[] arguments) {
165-
return getResolver(parameterContext).resolve(parameterContext, arguments);
164+
Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) {
165+
return getResolver(parameterContext).resolve(parameterContext, arguments, invocationIndex);
166166
}
167167

168168
private Resolver getResolver(ParameterContext parameterContext) {
@@ -213,9 +213,7 @@ Resolver createResolver(ParameterContext parameterContext) {
213213
}
214214

215215
interface Resolver {
216-
217-
Object resolve(ParameterContext parameterContext, Object[] arguments);
218-
216+
Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex);
219217
}
220218

221219
static class Converter implements Resolver {
@@ -229,7 +227,7 @@ static class Converter implements Resolver {
229227
}
230228

231229
@Override
232-
public Object resolve(ParameterContext parameterContext, Object[] arguments) {
230+
public Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) {
233231
Object argument = arguments[parameterContext.getIndex()];
234232
try {
235233
return this.argumentConverter.convert(argument, parameterContext);
@@ -252,8 +250,8 @@ static class Aggregator implements Resolver {
252250
}
253251

254252
@Override
255-
public Object resolve(ParameterContext parameterContext, Object[] arguments) {
256-
ArgumentsAccessor accessor = new DefaultArgumentsAccessor(arguments);
253+
public Object resolve(ParameterContext parameterContext, Object[] arguments, int invocationIndex) {
254+
ArgumentsAccessor accessor = new DefaultArgumentsAccessor(invocationIndex, arguments);
257255
try {
258256
return this.argumentsAggregator.aggregateArguments(accessor, parameterContext);
259257
}

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestParameterResolver.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ class ParameterizedTestParameterResolver implements ParameterResolver, AfterTest
3434

3535
private final ParameterizedTestMethodContext methodContext;
3636
private final Object[] arguments;
37+
private final int invocationIndex;
3738

38-
ParameterizedTestParameterResolver(ParameterizedTestMethodContext methodContext, Object[] arguments) {
39+
ParameterizedTestParameterResolver(ParameterizedTestMethodContext methodContext, Object[] arguments,
40+
int invocationIndex) {
3941
this.methodContext = methodContext;
4042
this.arguments = arguments;
43+
this.invocationIndex = invocationIndex;
4144
}
4245

4346
@Override
@@ -69,7 +72,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon
6972
@Override
7073
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
7174
throws ParameterResolutionException {
72-
return this.methodContext.resolve(parameterContext, extractPayloads(this.arguments));
75+
return this.methodContext.resolve(parameterContext, extractPayloads(this.arguments), this.invocationIndex);
7376
}
7477

7578
/**

junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,8 @@ public interface ArgumentsAccessor {
188188
*/
189189
List<Object> toList();
190190

191+
/**
192+
* Get the index of the current test invocation.
193+
*/
194+
int getInvocationIndex();
191195
}

junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@
3636
public class DefaultArgumentsAccessor implements ArgumentsAccessor {
3737

3838
private final Object[] arguments;
39+
private final int invocationIndex;
3940

40-
public DefaultArgumentsAccessor(Object... arguments) {
41+
public DefaultArgumentsAccessor(int invocationIndex, Object... arguments) {
4142
Preconditions.notNull(arguments, "Arguments array must not be null");
4243
this.arguments = arguments;
44+
this.invocationIndex = invocationIndex;
4345
}
4446

4547
@Override
@@ -126,4 +128,9 @@ public List<Object> toList() {
126128
return Collections.unmodifiableList(Arrays.asList(this.arguments));
127129
}
128130

131+
@Override
132+
public int getInvocationIndex() {
133+
return this.invocationIndex;
134+
}
135+
129136
}

junit-jupiter-params/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ private EngineExecutionResults execute(DiscoverySelector... selectors) {
208208
return EngineTestKit.execute("junit-jupiter", request().selectors(selectors).build());
209209
}
210210

211+
@ParameterizedTest
212+
@CsvSource({ "first", "second" })
213+
void argumentsAccessorInvocationIndex(ArgumentsAccessor arguments) {
214+
if ("first".equals(arguments.getString(0))) {
215+
assertEquals(1, arguments.getInvocationIndex());
216+
}
217+
if ("second".equals(arguments.getString(0))) {
218+
assertEquals(2, arguments.getInvocationIndex());
219+
}
220+
}
221+
211222
// -------------------------------------------------------------------------
212223

213224
public static class Person {

junit-jupiter-params/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,113 +31,113 @@ class DefaultArgumentsAccessorTests {
3131

3232
@Test
3333
void argumentsMustNotBeNull() {
34-
assertThrows(PreconditionViolationException.class, () -> new DefaultArgumentsAccessor((Object[]) null));
34+
assertThrows(PreconditionViolationException.class, () -> new DefaultArgumentsAccessor(1, (Object[]) null));
3535
}
3636

3737
@Test
3838
void indexMustNotBeNegative() {
39-
ArgumentsAccessor arguments = new DefaultArgumentsAccessor(1, 2);
39+
ArgumentsAccessor arguments = new DefaultArgumentsAccessor(1, 1, 2);
4040
Exception exception = assertThrows(PreconditionViolationException.class, () -> arguments.get(-1));
4141
assertThat(exception.getMessage()).containsSubsequence("index must be", ">= 0");
4242
}
4343

4444
@Test
4545
void indexMustBeSmallerThanLength() {
46-
ArgumentsAccessor arguments = new DefaultArgumentsAccessor(1, 2);
46+
ArgumentsAccessor arguments = new DefaultArgumentsAccessor(1, 1, 2);
4747
Exception exception = assertThrows(PreconditionViolationException.class, () -> arguments.get(2));
4848
assertThat(exception.getMessage()).containsSubsequence("index must be", "< 2");
4949
}
5050

5151
@Test
5252
void getNull() {
53-
assertNull(new DefaultArgumentsAccessor(new Object[] { null }).get(0));
53+
assertNull(new DefaultArgumentsAccessor(1, new Object[] { null }).get(0));
5454
}
5555

5656
@Test
5757
void getWithNullCastToWrapperType() {
58-
assertNull(new DefaultArgumentsAccessor((Object[]) new Integer[] { null }).get(0, Integer.class));
58+
assertNull(new DefaultArgumentsAccessor(1, (Object[]) new Integer[] { null }).get(0, Integer.class));
5959
}
6060

6161
@Test
6262
void get() {
63-
assertEquals(1, new DefaultArgumentsAccessor(1).get(0));
63+
assertEquals(1, new DefaultArgumentsAccessor(1, 1).get(0));
6464
}
6565

6666
@Test
6767
void getWithCast() {
68-
assertEquals(Integer.valueOf(1), new DefaultArgumentsAccessor(1).get(0, Integer.class));
69-
assertEquals(Character.valueOf('A'), new DefaultArgumentsAccessor('A').get(0, Character.class));
68+
assertEquals(Integer.valueOf(1), new DefaultArgumentsAccessor(1, 1).get(0, Integer.class));
69+
assertEquals(Character.valueOf('A'), new DefaultArgumentsAccessor(1, 'A').get(0, Character.class));
7070
}
7171

7272
@Test
7373
void getWithCastToPrimitiveType() {
7474
Exception exception = assertThrows(ArgumentAccessException.class,
75-
() -> new DefaultArgumentsAccessor(1).get(0, int.class));
75+
() -> new DefaultArgumentsAccessor(1, 1).get(0, int.class));
7676
assertThat(exception.getMessage()).isEqualTo(
7777
"Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [int].");
7878

7979
exception = assertThrows(ArgumentAccessException.class,
80-
() -> new DefaultArgumentsAccessor(new Object[] { null }).get(0, int.class));
80+
() -> new DefaultArgumentsAccessor(1, new Object[] { null }).get(0, int.class));
8181
assertThat(exception.getMessage()).isEqualTo(
8282
"Argument at index [0] with value [null] and type [null] could not be converted or cast to type [int].");
8383
}
8484

8585
@Test
8686
void getWithCastToIncompatibleType() {
8787
Exception exception = assertThrows(ArgumentAccessException.class,
88-
() -> new DefaultArgumentsAccessor(1).get(0, Character.class));
88+
() -> new DefaultArgumentsAccessor(1, 1).get(0, Character.class));
8989
assertThat(exception.getMessage()).isEqualTo(
9090
"Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [java.lang.Character].");
9191
}
9292

9393
@Test
9494
void getCharacter() {
95-
assertEquals(Character.valueOf('A'), new DefaultArgumentsAccessor('A', 'B').getCharacter(0));
95+
assertEquals(Character.valueOf('A'), new DefaultArgumentsAccessor(1, 'A', 'B').getCharacter(0));
9696
}
9797

9898
@Test
9999
void getBoolean() {
100-
assertEquals(Boolean.TRUE, new DefaultArgumentsAccessor(true, false).getBoolean(0));
100+
assertEquals(Boolean.TRUE, new DefaultArgumentsAccessor(1, true, false).getBoolean(0));
101101
}
102102

103103
@Test
104104
void getByte() {
105-
assertEquals(Byte.valueOf((byte) 42), new DefaultArgumentsAccessor((byte) 42).getByte(0));
105+
assertEquals(Byte.valueOf((byte) 42), new DefaultArgumentsAccessor(1, (byte) 42).getByte(0));
106106
}
107107

108108
@Test
109109
void getShort() {
110-
assertEquals(Short.valueOf((short) 42), new DefaultArgumentsAccessor((short) 42).getShort(0));
110+
assertEquals(Short.valueOf((short) 42), new DefaultArgumentsAccessor(1, (short) 42).getShort(0));
111111
}
112112

113113
@Test
114114
void getInteger() {
115-
assertEquals(Integer.valueOf(42), new DefaultArgumentsAccessor(42).getInteger(0));
115+
assertEquals(Integer.valueOf(42), new DefaultArgumentsAccessor(1, 42).getInteger(0));
116116
}
117117

118118
@Test
119119
void getLong() {
120-
assertEquals(Long.valueOf(42L), new DefaultArgumentsAccessor(42L).getLong(0));
120+
assertEquals(Long.valueOf(42L), new DefaultArgumentsAccessor(1, 42L).getLong(0));
121121
}
122122

123123
@Test
124124
void getFloat() {
125-
assertEquals(Float.valueOf(42.0f), new DefaultArgumentsAccessor(42.0f).getFloat(0));
125+
assertEquals(Float.valueOf(42.0f), new DefaultArgumentsAccessor(1, 42.0f).getFloat(0));
126126
}
127127

128128
@Test
129129
void getDouble() {
130-
assertEquals(Double.valueOf(42.0), new DefaultArgumentsAccessor(42.0).getDouble(0));
130+
assertEquals(Double.valueOf(42.0), new DefaultArgumentsAccessor(1, 42.0).getDouble(0));
131131
}
132132

133133
@Test
134134
void getString() {
135-
assertEquals("foo", new DefaultArgumentsAccessor("foo", "bar").getString(0));
135+
assertEquals("foo", new DefaultArgumentsAccessor(1, "foo", "bar").getString(0));
136136
}
137137

138138
@Test
139139
void toArray() {
140-
var arguments = new DefaultArgumentsAccessor("foo", "bar");
140+
var arguments = new DefaultArgumentsAccessor(1, "foo", "bar");
141141
var copy = arguments.toArray();
142142
assertArrayEquals(new String[] { "foo", "bar" }, copy);
143143

@@ -148,7 +148,7 @@ void toArray() {
148148

149149
@Test
150150
void toList() {
151-
var arguments = new DefaultArgumentsAccessor("foo", "bar");
151+
var arguments = new DefaultArgumentsAccessor(1, "foo", "bar");
152152
var copy = arguments.toList();
153153
assertIterableEquals(Arrays.asList("foo", "bar"), copy);
154154

@@ -158,9 +158,9 @@ void toList() {
158158

159159
@Test
160160
void size() {
161-
assertEquals(0, new DefaultArgumentsAccessor().size());
162-
assertEquals(1, new DefaultArgumentsAccessor(42).size());
163-
assertEquals(5, new DefaultArgumentsAccessor('a', 'b', 'c', 'd', 'e').size());
161+
assertEquals(0, new DefaultArgumentsAccessor(1).size());
162+
assertEquals(1, new DefaultArgumentsAccessor(1, 42).size());
163+
assertEquals(5, new DefaultArgumentsAccessor(1, 'a', 'b', 'c', 'd', 'e').size());
164164
}
165165

166166
}

junit-jupiter-params/src/test/kotlin/org/junit/jupiter/params/aggregator/ArgumentsAccessorKotlinTests.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ class ArgumentsAccessorKotlinTests {
2121

2222
@Test
2323
fun `get() with reified type and index`() {
24-
assertEquals(1, DefaultArgumentsAccessor(1).get<Int>(0))
25-
assertEquals('A', DefaultArgumentsAccessor('A').get<Char>(0))
24+
assertEquals(1, DefaultArgumentsAccessor(0, 1).get<Int>(0))
25+
assertEquals('A', DefaultArgumentsAccessor(0, 'A').get<Char>(0))
2626
}
2727

2828
@Test
2929
fun `get() with reified type and index for incompatible type`() {
3030
val exception = assertThrows<ArgumentAccessException> {
31-
DefaultArgumentsAccessor(Integer.valueOf(1)).get<Char>(0)
31+
DefaultArgumentsAccessor(0, Integer.valueOf(1)).get<Char>(0)
3232
}
3333

3434
assertThat(exception).hasMessage(
@@ -38,13 +38,13 @@ class ArgumentsAccessorKotlinTests {
3838

3939
@Test
4040
fun `get() with index`() {
41-
assertEquals(1, DefaultArgumentsAccessor(1).get(0))
42-
assertEquals('A', DefaultArgumentsAccessor('A').get(0))
41+
assertEquals(1, DefaultArgumentsAccessor(0, 1).get(0))
42+
assertEquals('A', DefaultArgumentsAccessor(0, 'A').get(0))
4343
}
4444

4545
@Test
4646
fun `get() with index and class reference`() {
47-
assertEquals(1, DefaultArgumentsAccessor(1).get(0, Integer::class.java))
48-
assertEquals('A', DefaultArgumentsAccessor('A').get(0, Character::class.java))
47+
assertEquals(1, DefaultArgumentsAccessor(0, 1).get(0, Integer::class.java))
48+
assertEquals('A', DefaultArgumentsAccessor(0, 'A').get(0, Character::class.java))
4949
}
5050
}

0 commit comments

Comments
 (0)