AssertJ 없이 테스트하는 경우
예외가 발생했는지 테스트하려면, 예외를 직접 catch 후 assertion을 수행해야 한다:
try {
// ...
} catch (Exception e) {
// assertions
}
하지만, 예외가 발생하지 않으면 테스트가 통과해 버리므로, 테스트가 실패하도록 명시적으로 설정하는 것이 필요하다. 이는 코드가 불필요하게 복잡해질 수 있음을 의미한다.
AssertJ로 테스트하기
Java 8 이상 버전부터는 AssertJ와 람다 표현식을 이용해 예외를 더 간단하게 검증할 수 있다.
`assertThatThrownBy()` 사용
리스트에서 인덱스가 범위를 벗어나는 경우, IndexOutOfBoundsException`이 발생하는 지 확인해보자.
assertThatThrownBy(() -> {
List<String> list = Arrays.asList("String one", "String two");
list.get(2);
}).isInstanceOf(IndexOutOfBoundsException.class)
.hasMessageContaining("Index: 2, Size: 2");
람다 표현식으로 예외가 발생할 코드를 전달하고, `isInstanceOf`와 다양한 AssertJ 메서드를 활용하여 메시지 검증까지 가능하다.
.hasMessage("Index: %s, Size: %s", 2, 2)
.hasMessageStartingWith("Index: 2")
.hasMessageContaining("2")
.hasMessageEndingWith("Size: 2")
.hasMessageMatching("Index: \\d+, Size: \\d+")
.hasCauseInstanceOf(IOException.class)
.hasStackTraceContaining("java.io.IOException");
`assertThatExceptionOfType ()` 사용
예외 타입을 먼저 지정하는 방법도 있다.
assertThatExceptionOfType(IndexOutOfBoundsException.class)
.isThrownBy(() -> {
// ...
}).hasMessageMatching("Index: \\d+, Size: \\d+");
자주 사용되는 예외 타입 전용 메서드
AssertJ는 흔히 사용되는 예외 타입에 대해 전용 메서드를 제공한다.
assertThatIOException().isThrownBy(() -> {
// 예외 발생 코드
});
다음과 같은 예외도 있다.
- `assertThatIllegalArgumentException()`
- `assertThatIllegalStateException()`
- `assertThatIOException()`
- `assertThatNullPointerException()`
예외를 별도로 분리하여 검증
예외를 따로 잡아 검증하는 방법도 있다.
// when
Throwable thrown = catchThrowable(() -> {
// ...
});
// then
assertThat(thrown)
.isInstanceOf(ArithmeticException.class)
.hasMessageContaining("/ by zero");
커스텀 예외의 필드 검증
AssertJ를 사용하면 커스텀 예외의 필드도 쉽게 검증할 수 있다. `catchThrowableOfType()` 메서드를 사용하면 특정 예외 타입만을 잡아낼 수 있다.
예제: `CityNotFoundException` 검증하기
먼저, 도시를 찾을 수 없을 때 발생할 커스텀 예외를 만든다. (Custom Exception 만들기)
public class CityNotFoundException extends RuntimeException {
private String city;
private String message;
CityNotFoundException(String city, String message) {
this.city = city;
this.message = message;
}
// Getters
}
public final class CityUtils {
private static final List<String> CITIES = Arrays.asList("Tamassint", "London", "Madrid", "New york");
public static String search(String searchedCity) {
return CITIES.stream()
.filter(searchedCity::equals)
.findFirst()
.orElseThrow(() -> new CityNotFoundException(searchedCity, "The specified city is not found"));
}
}
`CityNotFoundException` 예외는 지정된 도시가 존재하지 않을 때 발생한다.
@Test
public void whenUsingCatchThrowableOfType_thenAssertField() {
String givenCity = "Paris";
CityNotFoundException exception = catchThrowableOfType(() -> CityUtils.search(givenCity), CityNotFoundException.class);
assertThat(exception.getCity()).isEqualTo(givenCity);
assertThat(exception.getMessage()).isEqualTo("The specified city is not found");
}
또는 `assertThatThrownBy()`를 이용해 필드 값을 검증할 수 있다.
@Test
public void whenUsingAssertThatThrownBy_thenAssertField() {
String givenCity = "Geneva";
assertThatThrownBy(() -> CityUtils.search(givenCity)).isInstanceOf(CityNotFoundException.class)
.extracting("city")
.isEqualTo(givenCity);
}
여기서는 `extracting()` 메서드를 사용해 특정 필드를 추출하고, `isEqualTo()`로 필드 값을 검증했다.
참조
'Java' 카테고리의 다른 글
[Java] Enum이란? (0) | 2024.11.01 |
---|---|
[AssertJ] Custom Exception (0) | 2024.10.31 |
객체 지향 프로그래밍(Object-Oriented Programming, OOP) (0) | 2024.10.26 |
[JUnit] @Parameterized Test (0) | 2024.10.26 |
Google Java Style Guide (2) | 2024.10.25 |