JUnit 5 매개 변수 화 테스트 의 몇 가지 방식 을 상세 하 게 설명 합 니 다.

매개 변수 화 테스트 는 줄곧 흥미진진 한 화제 이다.우 리 는 JMeter 가 네 가지 매개 변수 화 방식 이 있다 는 것 을 알 고 있다.사용자 정의 변수,사용자 매개 변수,CSV 파일,함수 조수,그러면 JUnit 5 는 어떤 매개 변수 화 테스트 방식 이 있 습 니까?
의지 하 다
JUnit 5 는junit-jupiter-params의존 도 를 추가 해 야 매개 변 수 를 사용 할 수 있 습 니 다.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.7.2</version>
    <scope>test</scope>
</dependency>
단순 예시@ParameterizedTest매개 변수 화 테스트 를 정의 하고@ValueSource매개 변수 값 을 정의 합 니 다.

@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
void palindromes(String candidate) {
    assertTrue(StringUtils.isPalindrome(candidate));
}
실행 결과:

palindromes(String) ✔
├─ [1] candidate=racecar ✔
├─ [2] candidate=radar ✔
└─ [3] candidate=able was I ere I saw elba ✔
매개 변수 값 은 테스트 방법의 매개 변수 목록 과 일치 하고 순서대로 값 을 부여 합 니 다.여기 서 모두 3 개의 테스트 가 발생 했 습 니 다.
일곱 가지 방식
1 @ValueSource @ValueSource는 가장 간단 한 매개 변수 화 방식 으로 하나의 배열 로 다음 과 같은 데이터 형식 을 지원 합 니 다.
  • short
  • byte
  • int
  • long
  • float
  • double
  • char
  • boolean
  • java.lang.String
  • java.lang.Class
  • 예시:
    
    @ParameterizedTest
    @ValueSource(ints = { 1, 2, 3 })
    void testWithValueSource(int argument) {
        assertTrue(argument > 0 && argument < 4);
    }
    2 Null and Empty Sources@NullSource값 은 null 입 니 다.
    기원 유형의 테스트 방법 에 사용 할 수 없습니다.@EmptySource값 이 비어 있 고 테스트 방법의 매개 변수 류 에 따라 데이터 유형 을 결정 합 니 다.지원java.lang.String,java.util.List,java.util.Set,java.util.Map,기원 유형 배열int[],char[][]등,대상 배열String[],Integer[][]등)@NullAndEmptySource앞의 두 개 를 결합 시 켰 다.
    예시:
    
    @ParameterizedTest
    @NullSource
    @EmptySource
    @ValueSource(strings = { " ", "   ", "\t", "
    " }) void nullEmptyAndBlankStrings(String text) { assertTrue(text == null || text.trim().isEmpty()); }
    등가:
    
    @ParameterizedTest
    @NullAndEmptySource
    @ValueSource(strings = { " ", "   ", "\t", "
    " }) void nullEmptyAndBlankStrings(String text) { assertTrue(text == null || text.trim().isEmpty()); }
    3 @EnumSource매개 변수 화 된 값 은 매 거 진 형식 입 니 다.
    예시:
    
    @ParameterizedTest
    @EnumSource
    void testWithEnumSourceWithAutoDetection(ChronoUnit unit) {
        assertNotNull(unit);
    }
    그 중 크 로 노 유닛 은 날짜 매 거 진 클래스 입 니 다.
    ChronoUnit 은 인터페이스 TemporalUnit 의 실현 클래스 입 니 다.테스트 방법의 매개 변수 가 TemporalUnit 이면@EnumSource에 값 을 더 해 야 합 니 다.
    
    @ParameterizedTest
    @EnumSource(ChronoUnit.class)
    void testWithEnumSource(TemporalUnit unit) {
        assertNotNull(unit);
    }
    JUnit 5 가@EnumSource의 기본 값 의 유형 을 매 거 진 형식 으로 규정 하기 때문이다.
    names 속성 은 어떤 특정한 매 거 진 값 을 사용 할 지 지정 합 니 다:
    
    @ParameterizedTest
    @EnumSource(names = { "DAYS", "HOURS" })
    void testWithEnumSourceInclude(ChronoUnit unit) {
        assertTrue(EnumSet.of(ChronoUnit.DAYS, ChronoUnit.HOURS).contains(unit));
    }
    mode 속성 은 사용 모드 를 지정 하 는 데 사 용 됩 니 다.예 를 들 어 어떤 매 거 진 값 을 제외 합 니까?
    
    @ParameterizedTest
    @EnumSource(mode = EXCLUDE, names = { "ERAS", "FOREVER" })
    void testWithEnumSourceExclude(ChronoUnit unit) {
        assertFalse(EnumSet.of(ChronoUnit.ERAS, ChronoUnit.FOREVER).contains(unit));
    }
    예 를 들 어 정규 매 칭 을 사용 합 니 다.
    
    @ParameterizedTest
    @EnumSource(mode = MATCH_ALL, names = "^.*DAYS$")
    void testWithEnumSourceRegex(ChronoUnit unit) {
        assertTrue(unit.name().endsWith("DAYS"));
    }
    4 @MethodSource매개 변수 값 은 factory 방법 이 고 factory 방법 은 매개 변 수 를 가 져 갈 수 없습니다.
    예시:
    
    @ParameterizedTest
    @MethodSource("stringProvider")
    void testWithExplicitLocalMethodSource(String argument) {
        assertNotNull(argument);
    }
    
    static Stream<String> stringProvider() {
        return Stream.of("apple", "banana");
    }
    @TestInstance(Lifecycle.PER_CLASS)생명주기 가 아니면 factory 방법 은 static 이 어야 합 니 다.factory 방법의 반환 값 은Stream로 전환 할 수 있 는 유형 이다.예 를 들 어Stream,DoubleStream,LongStream,IntStream,Collection,Iterator,대상 배열 또는 기본 유형 배열 이다.예 를 들 어:
    
    @ParameterizedTest
    @MethodSource("range")
    void testWithRangeMethodSource(int argument) {
        assertNotEquals(9, argument);
    }
    
    static IntStream range() {
        return IntStream.range(0, 20).skip(10);
    }
    Iterable의 속성 을 생략 하면 JUnit Jupiter 는 테스트 방법 과 같은 이름 의 factory 방법 을 찾 습 니 다.예 를 들 어:
    
    @ParameterizedTest
    @MethodSource
    void testWithDefaultLocalMethodSource(String argument) {
        assertNotNull(argument);
    }
    
    static Stream<String> testWithDefaultLocalMethodSource() {
        return Stream.of("apple", "banana");
    }
    테스트 방법 에 여러 개의 인자 가 있다 면 factory 방법 도 여러 개 를 되 돌려 야 합 니 다.
    
    @ParameterizedTest
    @MethodSource("stringIntAndListProvider")
    void testWithMultiArgMethodSource(String str, int num, List<String> list) {
        assertEquals(5, str.length());
        assertTrue(num >=1 && num <=2);
        assertEquals(2, list.size());
    }
    
    static Stream<Arguments> stringIntAndListProvider() {
        return Stream.of(
            arguments("apple", 1, Arrays.asList("a", "b")),
            arguments("lemon", 2, Arrays.asList("x", "y"))
        );
    }
    이 중@MethodSource은 Arguments 인터페이스의 static factory method 로 바 꿀 수도 있다arguments(Object…).
    factory 방법 도 테스트 클래스 외부 방지:
    
    package example;
    
    import java.util.stream.Stream;
    
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.MethodSource;
    
    class ExternalMethodSourceDemo {
    
        @ParameterizedTest
        @MethodSource("example.StringsProviders#tinyStrings")
        void testWithExternalMethodSource(String tinyString) {
            // test with tiny string
        }
    }
    
    class StringsProviders {
    
        static Stream<String> tinyStrings() {
            return Stream.of(".", "oo", "OOO");
        }
    }
    5 Arguments.of(Object…)매개 변수 화 된 값 은 csv 형식의 데이터(기본 쉼표 구분)입 니 다.예 를 들 어:
    
    @ParameterizedTest
    @CsvSource({
        "apple,         1",
        "banana,        2",
        "'lemon, lime', 0xF1"
    })
    void testWithCsvSource(String fruit, int rank) {
        assertNotNull(fruit);
        assertNotEquals(0, rank);
    }
    delimiter 속성 은 구분 문 자 를 설정 할 수 있 습 니 다.delimiterString 속성 은 char 대신 구분자 문자열 을 설정 할 수 있 습 니 다.
    더 많은 입 출력 예 는 다음 과 같다.

    null 이 인용 한 목표 유형 이 기본 형식 이 라면 이상@CsvSource을 보고 합 니 다.
    6 ArgumentConversionException말 그대로 로 컬 csv 파일 을 데이터 원본 으로 선택 하 십시오.
    예시:
    
    @ParameterizedTest
    @CsvFileSource(resources = "/two-column.csv", numLinesToSkip = 1)
    void testWithCsvFileSourceFromClasspath(String country, int reference) {
        assertNotNull(country);
        assertNotEquals(0, reference);
    }
    
    @ParameterizedTest
    @CsvFileSource(files = "src/test/resources/two-column.csv", numLinesToSkip = 1)
    void testWithCsvFileSourceFromFile(String country, int reference) {
        assertNotNull(country);
        assertNotEquals(0, reference);
    }
    delimiter 속성 은 구분 문 자 를 설정 할 수 있 습 니 다.delimiterString 속성 은 char 대신 구분자 문자열 을 설정 할 수 있 습 니 다.특히 주의해 야 할 것 은@CsvFileSource시작 하 는 길드 가 주석 으로 여 겨 져 생략 되 었 다 는 점 이다.
    7 #사용자 정의 Arguments Provider.
    예시:
    
    @ParameterizedTest
    @ArgumentsSource(MyArgumentsProvider.class)
    void testWithArgumentsSource(String argument) {
        assertNotNull(argument);
    }
    public class MyArgumentsProvider implements ArgumentsProvider {
    
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
            return Stream.of("apple", "banana").map(Arguments::of);
        }
    }
    MyArguments Provider 는 외부 클래스 나 static 내부 클래스 여야 합 니 다.
    매개 변수 형식 변환
    암시 적 변환
    JUnit Jupiter 는 String 타 입 을 암시 적 으로 변환 합 니 다.예 를 들 면:
    
    @ParameterizedTest
    @ValueSource(strings = "SECONDS")
    void testWithImplicitArgumentConversion(ChronoUnit argument) {
        assertNotNull(argument.name());
    }
    더 많은 변환 예시:


    String 을 사용자 정의 대상 으로 변환 할 수도 있 습 니 다.
    
    @ParameterizedTest
    @ValueSource(strings = "42 Cats")
    void testWithImplicitFallbackArgumentConversion(Book book) {
        assertEquals("42 Cats", book.getTitle());
    }
    public class Book {
    
        private final String title;
    
        private Book(String title) {
            this.title = title;
        }
    
        public static Book fromTitle(String title) {
            return new Book(title);
        }
    
        public String getTitle() {
            return this.title;
        }
    }
    JUnit Jupiter 는@ArgumentsSource방법 을 찾 아Book.fromTitle(String)값 을 입력 한 후 String 유형 을 Book 형식 으로 변환 합 니 다.변 환 된 factory 방법 은 하나의 String 매개 변 수 를 받 아들 이 는 구조 방법 일 수도 있 고 하나의 String 매개 변 수 를 받 아들 여 목표 유형 을 되 돌려 주 는 일반적인 방법 일 수도 있 습 니 다.상세 한 규칙 은 다음 과 같다(공식 원문).

    현식 변환
    명시 적 변환 은 사용@ValueSource주석 이 필요 합 니 다.
    
    @ParameterizedTest
    @EnumSource(ChronoUnit.class)
    void testWithExplicitArgumentConversion(
            @ConvertWith(ToStringArgumentConverter.class) String argument) {
    
        assertNotNull(ChronoUnit.valueOf(argument));
    }
    그리고 Argument Converter 를 실현 합 니 다.
    
    public class ToStringArgumentConverter extends SimpleArgumentConverter {
    
        @Override
        protected Object convert(Object source, Class<?> targetType) {
            assertEquals(String.class, targetType, "Can only convert to String");
            if (source instanceof Enum<?>) {
                return ((Enum<?>) source).name();
            }
            return String.valueOf(source);
        }
    }
    단순 한 유형 전환 이 라면 TypedArgument Converter 를 실현 하면 됩 니 다.
    
    public class ToLengthArgumentConverter extends TypedArgumentConverter<String, Integer> {
    
        protected ToLengthArgumentConverter() {
            super(String.class, Integer.class);
        }
    
        @Override
        protected Integer convert(String source) {
            return source.length();
        }
    
    }
    JUnit Jupiter 는 자바 타임 아 그 먼 트 컨버터 하나만 내 장 했 습 니 다.@ConvertWith을 통 해 사용 합 니 다.
    
    @ParameterizedTest
    @ValueSource(strings = { "01.01.2017", "31.12.2017" })
    void testWithExplicitJavaTimeConverter(
            @JavaTimeConversionPattern("dd.MM.yyyy") LocalDate argument) {
    
        assertEquals(2017, argument.getYear());
    }
    매개 변수 집합
    테스트 방법의 여러 매개 변 수 는 Argument sAccessor 매개 변수 로 집합 한 다음 get 을 통 해 값 을 추출 할 수 있 습 니 다.예제:
    
    @ParameterizedTest
    @CsvSource({
        "Jane, Doe, F, 1990-05-20",
        "John, Doe, M, 1990-10-22"
    })
    void testWithArgumentsAccessor(ArgumentsAccessor arguments) {
        Person person = new Person(arguments.getString(0),
                                   arguments.getString(1),
                                   arguments.get(2, Gender.class),
                                   arguments.get(3, LocalDate.class));
    
        if (person.getFirstName().equals("Jane")) {
            assertEquals(Gender.F, person.getGender());
        }
        else {
            assertEquals(Gender.M, person.getGender());
        }
        assertEquals("Doe", person.getLastName());
        assertEquals(1990, person.getDateOfBirth().getYear());
    }
    Aggregator 를 사용자 정의 할 수도 있 습 니 다.
    
    public class PersonAggregator implements ArgumentsAggregator {
        @Override
        public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) {
            return new Person(arguments.getString(0),
                              arguments.getString(1),
                              arguments.get(2, Gender.class),
                              arguments.get(3, LocalDate.class));
        }
    }
    그리고@JavaTimeConversionPattern를 통 해 사용 합 니 다.
    
    @ParameterizedTest
    @CsvSource({
        "Jane, Doe, F, 1990-05-20",
        "John, Doe, M, 1990-10-22"
    })
    void testWithArgumentsAggregator(@AggregateWith(PersonAggregator.class) Person person) {
        // perform assertions against person
    }
    조합 주 해 를 통 해 우 리 는 코드 를 더욱 간소화 할 수 있다.
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    @AggregateWith(PersonAggregator.class)
    public @interface CsvToPerson {
    }
    @ParameterizedTest
    @CsvSource({
        "Jane, Doe, F, 1990-05-20",
        "John, Doe, M, 1990-10-22"
    })
    void testWithCustomAggregatorAnnotation(@CsvToPerson Person person) {
        // perform assertions against person
    }
    사용자 정의 디 스 플레이 이름
    매개 변수 화 테스트 로 생 성 된 test,JUnit Jupiter 는 기본 이름 을 정 했 습 니 다.name 속성 을 통 해 사용자 정의 할 수 있 습 니 다.
    예시:
    
    @DisplayName("Display name of container")
    @ParameterizedTest(name = "{index} ==> the rank of ''{0}'' is {1}")
    @CsvSource({ "apple, 1", "banana, 2", "'lemon, lime', 3" })
    void testWithCustomDisplayNames(String fruit, int rank) {
    }
    결과:
    
    Display name of container ✔
    ├─ 1 ==> the rank of 'apple' is 1 ✔
    ├─ 2 ==> the rank of 'banana' is 2 ✔
    └─ 3 ==> the rank of 'lemon, lime' is 3 ✔
    표시 하려 면@AggregateWith두 겹'apple'을 사용 해 야 합 니 다.name 은 Message Format 이기 때 문 입 니 다.
    자리 차지 문자 설명 은 다음 과 같 습 니 다.

    작은 매듭
    본 고 는 JUnit 5 매개 변수 화 테스트 의 7 가지 방식 을 소개 했다.각각''apple'',Null and Empty Sources,@ValueSource,@EnumSource,@MethodSource,@CsvSource,@CsvFileSource로 자바 문법 에 치 우 쳐 JUnit 단원 테스트 프레임 워 크 의 특징 에 부합된다.또 JUnit Jupiter 의 매개 변수 유형 변환 과 매개 변수 집합 도 소개 했다.마지막 으로 매개 변수 화 테스트 의 이름 을 사용자 정의 하려 면 name 속성 을 사용 하여 구현 할 수 있 습 니 다.
    참고 자료:
    https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
    JUnit 5 매개 변수 화 테스트 의 몇 가지 방식 에 대한 상세 한 설명 을 담 은 이 글 은 여기까지 입 니 다.더 많은 JUnit 5 매개 변수 화 테스트 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 읽 어 주시 기 바 랍 니 다.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기