AssertJ 의 장점.
- 메소드 체이닝을 지원하기 때문에 깔끔하고 읽기 쉬운 테스트 코드를 작성할 수 있다.
- JUnit 만으로는 부족한 테스트 기능을 거의 대부분 제공합니다.
간단한 예.
모든 테스트 코드는 assertThat() 메소드에서 출발합니다.
assertThat().메소드().메소드2().메소드3()
# 문자열 테스트
assertThat("Hello, world! Nice to meet you.") // 주어진 "Hello, world! Nice to meet you."라는 문자열은
.isNotEmpty() // 비어있지 않고
.contains("Nice") // "Nice"를 포함하고
.contains("world") // "world"도 포함하고
.doesNotContain("ZZZ") // "ZZZ"는 포함하지 않으며
.startsWith("Hell") // "Hell"로 시작하고
.endsWith("u.") // "u."로 끝나며
.isEqualTo("Hello, world! Nice to meet you."); // "Hello, world! Nice to meet you."과 일치합니다.
# 숫자 테스트
assertThat(3.14d) // 주어진 3.14라는 숫자는
.isPositive() // 양수이고
.isGreaterThan(3) // 3보다 크며
.isLessThan(4) // 4보다 작습니다
.isEqualTo(3, offset(1d)) // 오프셋 1 기준으로 3과 같고
.isEqualTo(3.1, offset(0.1d)) // 오프셋 0.1 기준으로 3.1과 같으며
.isEqualTo(3.14); // 오프셋 없이는 3.14와 같습니다
AssertJ 사용 방법.
@Test
void 자동차_이름_입력값_반환() {
List<String> cars = inputPaser.toList("pobi,woni");
assertEquals(cars.size(), 2);
assertEquals(cars.get(0), "pobi");
assertEquals(cars.get(1), "woni");
}
위 테스트는 기본적인 JUnit 라이브러리만을 사용하여 테스트를 작성한 코드입니다. 우선 AssertJ 에서 제공하는 메서드를 체이닝 하기에 앞서 assertEquals() 를 assertThat() 으로 바꾸도록하겠습니다.
@Test
void 자동차_이름_입력값_반환() {
List<String> cars = inputPaser.toList("pobi,woni");
assertThat(cars.size()).isEqualTo(2);
assertThat(cars).contains("pobi");
assertThat(cars).contains("woni");
}
뭔가 가독성이 좋아진 것 같죠? 또 Assertion 은 반복 가능한 컬렉션이나 배열에 대해 내용을 확인할 수 있도록 하는 다양한 방법을 제공합니다. 지금 위에 사용된 contains() 또한 주어진 값이 어떤 순서로든 선언된 객체에 포함되어 있는지 확인합니다. 아래와 같이 여러 값을 비교할 수도 있습니다.
@Test
void 자동차_이름_입력값_반환() {
List<String> cars = inputPaser.toList("pobi,woni");
assertThat(cars.size()).isEqualTo(2);
assertThat(cars).contains("pobi", "woni");
}
List<String> 이 아닌 List<Car> 에 대한 객체 컬렉션이 있다고 했을 때 특정 필드나 속성만 extracting() 을 사용하여 추출하는 방법도 있습니다.
@Test
void 레이싱_참가_자동차_요소_확인() {
List<String> names = List.of("pobi","woni");
Cars cars = new Cars(names);
List<Car> list = cars.getCars();
assertThat(list).extracting(Car::getName)
.contains("pobi","woni");
// 혹은 필드명
assertThat(list).extracting("name")
.contains("pobi","woni");
}
여기서 더 나아가서 여러 속성을 지정하고 비교하는데 tuple 을 사용할 수도 있습니다.
@Test
void 레이싱_참가_자동차_요소_확인() {
List<String> names = List.of("pobi","woni");
Cars cars = new Cars(names);
List<Car> list = cars.getCars();
assertThat(list).extracting("name", "position")
.contains(tuple("pobi", 0),
tuple("woni", 0));
}
다음으로는 예외 Assertion 에 대해서 알아보겠습니다. 개인적으로는 TDD 에서는 예외 테스트가 중요하다고 생각하는데요. 여러 방법이 있지만 대표적인 방법은 아래와 같으며 자신이 편한 방법으로 사용하면 될 것 같습니다.
@Test
void 이름_사이에_공백이_존재하는_경우() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> inputParser.toList("pobi,wo ni"));
assertThatIllegalArgumentException()
.isThrownBy(() -> inputParser.toList("pobi,wo ni"));
assertThatThrownBy(() -> inputParser.toList("pobi,wo ni"))
.isInstanceOf(IllegalArgumentException.class);
}
비슷한 기능으로는 아래와 같습니다.
- assertThatIllegalArgumentException()
- assertThatIllegalStateException()
- assertThatIOException()
- assertThatNullPointerException()
여기서 inputPaser 는 쉼표 사이에 공백이 존재하면 IllegalArgumentException 을 던지고 있습니다. 에러 메시지로는 "이름 사이에 공백이 존재해서는 안됩니다." 라는 메시지를 던지고 있죠. 이것이 정확히 일치하는지 검사해보겠습니다.
@Test
void 쉼표_사이에_공백이_존재하는_경우() {
assertThatThrownBy(() -> inputParser.toList("pobi, woni"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("이름 사이에 공백이 존재해서는 안됩니다.")
// check start
.hasMessageStartingWith("이름")
// check contain
.hasMessageContaining("이름 사이")
// check end
.hasMessageEndingWith("안됩니다.")
// check regex
.hasMessageMatching("이름 사이에 .*")
// check does not contain
.hasMessageNotContaining("체크");
}
예외 상황이 발생한 상황을 확인할 수도 있지만 반대로 예외가 발생하지 않는지에 대한 테스트도 가능합니다.
assertThatNoException().isThrownBy(() -> inputParser.toList("pobi,woni"));
마치며.
이외에도 여러 기능이 있지만 TDD 를 하고자 한다면 복잡한 상황을 가정하여 테스트하기 보다는 단순한 테스트를 작성하면서 그에 맞는 기능들을 만들어내야 하기에 이정도의 기능만 알고 있어도 충분하다는 생각이 듭니다. 앞에 내용에서 틀린 부분이 있다면 댓글로 남겨주시면 감사하겠습니다.
참고자료
https://www.daleseo.com/assertj/
https://assertj.github.io/doc/
'시리즈 > 자바' 카테고리의 다른 글
[JAVA] Enum 열거 타입에 대해 알아보기 ① (0) | 2024.10.29 |
---|---|
[JAVA] static 과 final 의 의미와 관계 (0) | 2024.10.27 |
[TEST] 테스트를 위한 JUnit 5 와 AssertJ ① (1) | 2024.10.24 |
[JAVA] 몰라서 못 썼던 정규 표현식을 알아보자 ④ (1) | 2024.10.22 |
[JAVA] 몰라서 못 썼던 정규 표현식을 알아보자 ③ (0) | 2024.10.21 |