StringTest

1. contains

  • 용도 : 배열이나 컬렉션이 특정 요소들을 포함하고 있는지 검증할때 사용
  • 순서 무관
  • 부분일치 허용 : 배열이나 컬렉션에 더 만은 요소가 있어도 지정한 요소들이 모두 포함되어있다면 테스트 통과

2. containsExactly

  • 용도 : 배열이나 컬렉션의 요소들이 정확히 일치하는지 검증할 때 사용
  • 순서 상관 있음 : 배열이나 컬렉션의 요소가 정확히 같은 순서로 있어야 함
  • 완전 일치 : 지정된 요소들이 배열이나 컬렉션의 요소들과 순서와 내용까지 모두 일치해야 테스트 통과
** 주어진 구분자가 문자열 내에 없을 경우, 전체 문자열을 하나의 요소로 간주하여 반환한다 **

@Test
    @DisplayName("문자열을 ','로 분리했을 때 올바르게 분리되는지 확인")
    void splitTest() {
        //given
        String input1 = "1,2,3";
        String input2 = "1";

        //when
        String[] result1 = input1.split(",");
        String[] result2 = input2.split(",");

        //then
        assertThat(result1).contains("1", "2"); // 통과
//        assertThat(result1).containsExactly("1", "2");   3이 빠졌으므로 -> X
        assertThat(result2).contains("1"); // 통과
        assertThat(result2).containsExactly("1"); // 통과
    }
    
Expected :[1, 2]
Actual   :[1, 2, 3]

 

3. assertThatThrownBy

  • 용도 : 특정 코드 블록이 예외를 발생시키는지 검증할 때 사용
  • 포괄적인 예외 검증 : 특정 예외 타입이 아니라 예외 발생 자체에 중점을 두며, 예외 타입과 메시지를 함께 검증할 수 있다.
  • 메시지 검증 : 예외 메시지를 검증
    • hasMessageContaining(String text) :
      • 예외 메시지에 특정 문자열이 포함되어 있는지 검증
      • 부분 문자열 일치만을 확인하기 때문에, 메시지의 일부분만 검증할때 유용

4. assertThatExceptionOfType

  • 용도 : 특정 예외 타입이 발생하는지 명확히 검증할 때 사용
  • 예외 타입 명시 : 예외 타입을 처음부터 지정하여 해당 타입의 예외가 발생하는지 명확히 드러냄
  • 메시지와 원인 검증 : 메시지와 원인까지 세밀하게 검증
    • withMessage(String message)
      • 예외 메시지가 정확히 일치하는지 검증 %s, %d 같은 서식 문자와 사용 가능 
    • withMessageContaining(String text)
      • 예외 메시지에 특정 문자열이 포함되어 있는지 검증
      • hasMessageContaining과 같은 역할이지만 assertThatExceptionOfType와 사용
    • withMessageMatching(String regex)
      • 예외 메시지가 정규 표현식과 일치하는지 검증
    • withNoCause()
      • 예외에 원인(cause)이 없는지를 검증
      • 외가 다른 예외에 의해 발생하지 않았음을 확인
    • isThrownBy(() -> { // 예외가 발생할 코드})
      • 람다 표현식 : 예외를 발생시키는 코드를 람다 표현식으로 작성한다.
      • 예외 발생 코드 : 직접 예외를 throw 하거나 , 특정 조건에서 예외를 발생시키는 메소드를 호출한다.
1. hasMessageContaining(String text)

assertThatThrownBy(() -> { throw new Exception("Something went wrong: Error code 123"); })
    .isInstanceOf(Exception.class)
    .hasMessageContaining("Error code");  
    // "Error code"가 메시지에 포함되어 있는지 확인


2. withMessage(String message)

assertThatExceptionOfType(IOException.class)
    .isThrownBy(() -> { throw new IOException("Error code: 404"); })
    .withMessage("Error code: %d", 404);  
    // 정확히 일치하는지 서식 문자 %d를 사용해 메시지 검증


3. withMessageContaining(String text)

assertThatExceptionOfType(IllegalArgumentException.class)
    .isThrownBy(() -> { throw new IllegalArgumentException("Invalid argument: value too high"); })
    .withMessageContaining("value too high");  
    // 메시지에 "value too high"가 포함되어 있는지 확인


4. withMessageMatching(String regex)

assertThatExceptionOfType(IndexOutOfBoundsException.class)
    .isThrownBy(() -> { throw new IndexOutOfBoundsException("Index: 5, Size: 3"); })
    .withMessageMatching("Index: \\d+, Size: \\d+");  
    // "Index: 숫자, Size: 숫자" 형식 검증


5. withNoCause()

assertThatExceptionOfType(IOException.class)
    .isThrownBy(() -> { throw new IOException("boom!"); })
    .withNoCause(); 
    // 예외에 원인이 없는지 확인
    
    
6. isThrownBy(() -> { // 예외가 발생할 코드})

assertThatExceptionOfType(IOException.class)
    .isThrownBy(() -> {
        throw new IOException("File not found");
    })
    .withMessage("File not found");
    
assertThatExceptionOfType(StringIndexOutOfBoundsException.class)
    .isThrownBy(() -> {
        String str = "abc";
        char ch = str.charAt(5); // 유효하지 않은 인덱스 접근
    })
    .withMessageMatching("String index out of range: \\d+");

 

  • 자주 발생하는 Exception의 경우 Exception 별 메소드 제공
    • assertThatIllegalArgumentException()
    • assertThatIllegalStateException()
    • assertThatIOException()
    • assertThatNullPointerException()

 

Set Collection Test

1. BeforeEach && AfterEach

 

  • beforeEach : 각 테스트가 실행되기 전에 특정 작업을 수행하고자 할 때 사용. 테스트마다 공통적으로 설정해야 하는 초기화 작업을 설정
  • afterEach : 각 테스트가 끝난 후에 특정 작업을 수행하고자 할 때 사용. 주로 리소스 정리, 데이터 초기화 등과 같은 작업을 수행하는 데 사용
private Set<Integer> numbers;
@BeforeEach
void setUp(){
    numbers = new HashSet<>();
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
}

@AfterEach
void tearDown(){
    numbers.clear();
    System.out.println("AfterEach: Set이 초기화되었습니다.");
}

 

 

2. ParameterizedTest

 

  • 중복 코드 감소 : 다양한 입력 값으로 테스트할 수 있어, 반복적으로 비슷한 코드를 작성하지 않음
  • 가독성 향상 : 입력 값만 다를 뿐 같은 로직을 테스트하는 경우, 테스트 코드를 간결하게 유지 가능
  • 유연한 데이터 입력 : 다양한 데이터 소스와 함께 사용하여, 원하는 데이터를 손쉽게 전달 가능
    • 데이터소스
      • ValueSource : 단일 파라미터의 배열 형태로 데이터를 전달할 때 사용
      • CsvSource : 여러 인자를 CSV 형식으로 전달할 때 사용
      • CsvFileSource : 외부 CSV 파일을 데이터 소스로 사용할 때 유용
      • EnumSource : 특정 enum 타입의 값으로 테스트를 반복할 때 사용
      •  MethodSource : 메소드에서 직접 데이터를 생성해 테스트에 사용
      •  ArgumentsSource : 사용자 정의 ArgumentsProvider를 사용해 원하는 데이터 형식으로 값을 전달
1.@ValueSource

@ParameterizedTest
@ValueSource(ints = {1, 3, 5})
void testIsOdd(int number) {
    assertTrue(number % 2 != 0);
}


2.@CsvSource

@ParameterizedTest
@CsvSource({"apple, 5", "banana, 6", "cherry, 6"})
void testStringLength(String word, int expectedLength) {
    assertEquals(expectedLength, word.length());
}


3.@CsvFileSource

@ParameterizedTest
@CsvFileSource(resources = "/data.csv", numLinesToSkip = 1) // 첫 줄은 헤더
void testStringLengthFromFile(String word, int expectedLength) {
    assertEquals(expectedLength, word.length());
}


4.@EnumSource

@ParameterizedTest
@EnumSource(Fruit.class) // Fruit는 enum 타입
void testEnum(Fruit fruit) {
    assertNotNull(fruit); // enum 값이 null이 아닌지 확인
}


5.@MethodSource

@ParameterizedTest
@MethodSource("provideNumbers")
void testGreaterThanZero(int number) {
    assertTrue(number > 0);
}

static Stream<Integer> provideNumbers() {
    return Stream.of(1, 2, 3);
}


6.@ArgumentsSource

@ParameterizedTest
@ArgumentsSource(CustomArgumentsProvider.class)
void testStringLength(String word, int expectedLength) {
    assertEquals(expectedLength, word.length());
}

 

+ Recent posts