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