2

I'm using JUnit 5.7.0, IntellijIDEA 2021.1.2 CE, MacOS Catalina 10.15. and don't understand the difference between ParameterizedTest.ARGUMENTS_PLACEHOLDER and ParameterizedTest.ARGUMENTS_WITH_NAMES_PLACEHOLDER.

According to the javadoc ARGUMENTS_WITH_NAMES_PLACEHOLDER deals with named arguments whereas ARGUMENTS_PLACEHOLDER with just arguments. The test result in IDEA for both tests looks the same:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

@ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithArguments(String fruit, int rank) {
}

@ParameterizedTest(name = ARGUMENTS_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithNamedArguments(String fruit, int rank) {
}

enter image description here

Can anyone provide an example where these two placeholders behave differently?

Nikita Protskiy
  • 75
  • 1
  • 1
  • 5

3 Answers3

3

Solution

For ARGUMENTS_WITH_NAMES_PLACEHOLDER to work as expected, tests must be compiled with
-parameters flag. Then, argument names will be 1) stored, and 2) be able to be subsequently retrieved by JUnit via reflection.

In Practice

For Java projects built with Gradle, the following would enable this flag specifically for tests:

tasks.named('compileTestJava') {
    options.compilerArgs += '-parameters'
}

Reference

  • From Java 8 documentation on javac:

    -parameters Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them.

  • Naturally, JUnit is using reflection to get parameter names. For instance, check out ParameterizedTestMethodContext#getParameterName (example from v5.7.1).

1

If you use @ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER) you'll get output result with parameterName + "=" + paraveterValue.

But if you use @ParameterizedTest(name = ARGUMENTS_PLACEHOLDER) you'll get only paraveterValue

Also, you can see that in javadoc:

Placeholder for the complete, comma-separated named arguments list of the current invocation of a @ParameterizedTest method: {argumentsWithNames}

@API(status = EXPERIMENTAL, since = "5.6")
String ARGUMENTS_WITH_NAMES_PLACEHOLDER = "{argumentsWithNames}";

Default display name pattern for the current invocation of a @ParameterizedTest method: "[{index}] {argumentsWithNames}"
Note that the default pattern does not include the display name of the @ParameterizedTest method.

@API(status = EXPERIMENTAL, since = "5.3")
String DEFAULT_DISPLAY_NAME = "[" + INDEX_PLACEHOLDER + "] " + ARGUMENTS_WITH_NAMES_PLACEHOLDER;

I tried to run your code like that:

@ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER)
@CsvSource({"apple, 1", "banana, 2", "'lemon, lime', 3" })
void testWithNamedArguments(String fruit, int rank) {
}

and I got the correct result:

enter image description here

I use jupiter 5.6.3, the feature ARGUMENTS_WITH_NAMES_PLACEHOLDER appeared since 5.6 version.

Dmitrii B
  • 2,672
  • 3
  • 5
  • 14
  • So then why is the test result for {argumentsWithNames} not "fruit = apple , rank = 1" etc., but just "apple, 1" . Or prolly parameterName should be specified separately somehow via additional annotations ? – Nikita Protskiy Jun 27 '21 at 13:30
  • I see the same result as OP originally, but after maven reload project in IDEA, I see the result as answer. – samabcde Jun 27 '21 at 13:45
  • OP can you try to execute maven goal mvn clean -am and then try to run with ARGUMENTS_WITH_NAMES_PLACEHOLDER parameter, maybe your test uses the oldest compile data – Dmitrii B Jun 27 '21 at 13:47
  • I'm using Gradle. I've rebuilt test, but nothing changed. I thought that there is an issue on IDEA side because in official tutorial video test's output doesn't have parameter's name as well: https://youtu.be/we3zJE3hlWE?t=879 . On top of that I've tried to run tests via ConsoleLauncher: ` java -jar junit-platform-console-standalone-1.7.2.jar -cp ./build/classes/java/test --scan-classpath` and output also doesn't have names. So it seems I had to ask another question: smth like: why {argumentsWithNames} placeholder doesn't work. – Nikita Protskiy Jul 16 '21 at 14:45
  • @DmitriiB Can I fix the `paraveterValue`? I just can't sleep. – Jin Kwon Jun 05 '22 at 07:00
0

Regarding the -parameter option, if you stand still with Apache Maven,

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <parameters>true</parameters>
          </configuration>
        </plugin>
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184