24일차
오늘은 Part 2. 게시판 서비스 강의의 `게시판 페이지 기능 테스트 정의` 부분을 학습하였다.
게시글과 댓글 서비스 로직의 테스트를 작성하고 서비스 부분 코드의 골격을 잡는 부분을 학습하였다.
Mockito
Mock 객체를 쉽게 만들고, 관리하고, 검증할 수 있는 방법을 제공하는 프레임워크이다.
스프링 테스트 패키지에 포함되어 있기 때문에 따로 설치할 필요가 없다.
프로젝트에서
@ExtendWith(MockitoExtention.class)
로 사용해주었다.
BDD
Behavior-Driven Development의 약자로 행위 주도 개발을 말한다.
테스트 대상의 상태의 변화를 테스트하는 것이고, 시나리오를 기반으로 테스트하는 패턴을 권장한다.
여기서 권장하는 기본 패턴은 Given, When, Then 구조를 가진다.
BDDMockito
Mockito을 상속한 클래스이다. 동작이나 사용하는 방법 또한 Mockito와 거의 차이가 없다.
BDDMockito는 BDD를 사용하여 테스트 코드를 작성할 때, 시나리오에 맞게 테스트 코드가 읽힐 수 있도록 도와주는 프레임워크이다.
BDDMockito가 제공하는 기능과 Mockito가 제공하는 기능은 별반 다르지 않다.
단지 BDD라는 것을 테스트 코드에 도입할 때 기존의 Mockito가 가독성을 해치지 때문에 이를 해결하기 우한 기능은 같지만 이름만 다른 클래스라고 생각하면 된다.
테스트 코드 - BDDMockito 사용
게시글을 조회하면, 게시글을 반환한다.
@DisplayName("게시글을 검색하면, 게시글 리스트를 반환")
@Test
void givenSearchParameters_whenSearchingArticles_thenReturnsArticleList(){
// Given
// When
Page<ArticleDto> articles = sut.searchArticles(SearchType.TITLE, "search keyword"); // 제목, 본문. ID, 닉네임, 해시태그
// Then
assertThat(articles).isNotNull();
}
게시글 정보를 입력하면, 게시글을 생성한다.
@DisplayName("게시글 정보를 입력하면, 게시글을 생성한다.")
@Test
void givenArticleInfo_whenSavingArticle_thenSavesArticle() {
// Given
given(articleRepository.save(ArgumentMatchers.any(Article.class))).willReturn(null);
// When
sut.saveArticle(ArticleDto.of(LocalDateTime.now(),"sarang","title1","content1","#spring"));
// Then
then(articleRepository).should().save(any(Article.class));
}
게시글의 ID와 수정 정보를 입력하면, 게시글을 수정한다.
@DisplayName("게시글의 ID와 수정 정보를 입력하면, 게시글을 수정한다.")
@Test
void givenArticleIdAndModifiedInfo_whenUpdatingArticle_thenUpdatesArticle() {
// Given
given(articleRepository.save(ArgumentMatchers.any(Article.class))).willReturn(null);
// When
sut.updateArticle(1L, ArticleUpdateDto.of("title1","content1","#spring"));
// Then
then(articleRepository).should().save(any(Article.class));
}
게시글의 ID를 입력하면, 게시글을 삭제한다.
@DisplayName("게시글의 ID를 입력하면, 게시글을 삭제한다.")
@Test
void givenArticleId_whenDeletingArticle_thenDeletesArticle() {
// Given
willDoNothing().given(articleRepository).delete(ArgumentMatchers.any(Article.class));
// When
sut.deleteArticle(1L);
// Then
then(articleRepository).should().delete(any(Article.class));
}