How to parameterize with String arrays in JUnit 5

后端 未结 3 2083
不思量自难忘°
不思量自难忘° 2021-02-07 14:17

I would like to write JUnit 5 parametrized test which takes string array (String[]) as a parameter:



        
相关标签:
3条回答
  • 2021-02-07 14:49

    Use the Arguments.of() factory from org.junit.jupiter.params.provider.Arguments to wrap your arguments:

    static Stream<Arguments> stringArrayProvider() {
        return Stream.of(
                Arguments.of((Object) new String[]{"1", "2"}),
                Arguments.of((Object) new String[]{"1", "2", "3"})
        );
    }
    

    For details see http://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests

    0 讨论(0)
  • 2021-02-07 14:52

    An alternative for Sormuras' solution can be usage of the annotation @ArgumentsSource which works in very similar manner:

    static class StringArrayProvider implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
            return Stream.of(
                    (Object) new String[]{"1", "2"},
                    (Object) new String[]{"1", "2", "3"}).map(Arguments::of);
        }
    }
    

    Still, casting String[] to Object looks strange and I have rather feeling of workaround than of nice design.

    0 讨论(0)
  • 2021-02-07 15:00

    First one general rule of thumb that I use:

    • use @ArgumentSource (your solution) when the same generated test cases can be used by more than one Test Class

    • use @MethodSource (Sormuras solution) when the same generated test cases can be used by more than one Test Method (in the same class)

    • otherwise try to keep the source for test cases as local as possible to the method that uses them

    In this last situation I envision two simple possibilities:

    1. you are interested in a fixed number of strings (so not really need for an array). You can use @CsvSource

      Here there is an example for two strings (possibly including commas too).

      @ParameterizedTest
      @CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
      void testWithCsvSource(String first, String second) {
          assertNotNull(first);
          assertNotEquals(0, second);
      }
      

      Note that in this case, if the various elements are not really strings they can be probably automatically parsed to the correct types (e.g., in your question it seems that you want integers)

    2. you want really a variable size array of Strings. In this case you can use @ValueSource and then convert its content to String[]

      directly:

      @ParameterizedTest
      @ValueSource(strings = {"1, 2",
                              "1, 2, 3"})
      void testWithArrayOfStrings(String arg) {       // the single csv String parameter
        String[] arrayParam = arg.split("\\s*,\\s*"); // is converted to an array of Strings
        ...
      }
      

      or with an Explicit Converter class indicated by @ConvertWith :

      @ParameterizedTest
      @ValueSource(strings={"1, 2", "1, 2, 3"})
      void testWithArrayOfStrings(@ConvertWith(CSVtoArray.class)String... arg) 
      {
        ...
      }
      
      public static class CSVtoArray extends SimpleArgumentConverter {
        @Override
        protected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
          String s = (String) source;
          return s.split("\\s*,\\s*");
        }
      }
      
    0 讨论(0)
提交回复
热议问题