저번에 설계한 API를 본격적으로 구현한다.
하지만 전에 만든 테스트 작업을 통해서 회원가입과 로그인과 관련된 기능을 제외하고는 게시판과 댓글의 api는 제작이 거의 완료된 상태이다.
spring data REST 를 사용해서 이전에 제작한 엔티티와 리포지토리를 이용하여 RESTFUL API를 제작한다. 복잡한 데이터를 전달하고자 할때는 별도로 만들어서 보충한다.
spring initializr 를 통해서 Rest Repositories
와 Rest Repositories HAL Explorer
를 Dependencies에 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.data:spring-data-rest-hal-explorer'
application.ymal 옵션 추가
data.rest:
base-path: /api
detection-strategy: annotated
repository 모든 하위 파일에 어노테이션@RepositoryRestResource
추가
@RepositoryRestResource
이제 어플리케이션을 실행한 상태로 https://localhost:8080/api를 치고 들어가면(만약 "localhost에서 잘못된 응답을 전송했습니다." 라는 문구가 나타나면 https 대신 http로 입력하면 나타난다.)
사이트가 나타난다. 이때 HAL explorer는 이전에 만든 api를 테스트해보기 위해 사용한다.
게시글과 댓글을 GET메소드로 확인해 볼수 있고, 게시글에 댓글이 어느정도 존재하는지도 알수 있다.
예를 들어서 15번째 게시글에 존재하는 모든 댓글을 보여주는 GET메서드를 실행하면
이런식으로 댓글을 전부 보여주게 된다.
API테스트를 하려고 했으나 이미 이전에 API가 전반적으로 구현이 된 상태이므로 data REST기능을 테스트한다.
처음에 Dependencies
에 추가한 Rest Repository의 data REST를 테스트한다.
프로젝트에서 test/java/projectname 에 controller라는 패키지를 만들고 그 안에 DataRestTest.java를 생성한다.
api/articles의 경로가 존재하는가? 그리고 있다면 경로의 content타입은 검사대상과 일치하는가? 를 테스트한다.
이렇게 한 상태로 테스트를 돌리면 404 오류가 나타나면서 실패한다. 근데 막상 http://localhost:8080/api/articles로 들어가보면 잘 나타나있는데 이유가 뭘까?
WebMvcTest는 슬라이스 테스트로 레이어별로 잘라서, 레이어를 하나의 단위로 보는 단위 테스트인데 컨트롤러 외의 bean들을 로드 하지 않았기 때문이다(data REST의 autoconfiguration).
로드되지 않은 bean들을 따로 넣는 방법이 있지만 그 대신에 @SpringBootTest
를 사용한다.
또한 MockMvc의 존재를 알기 위한 @AutoConfigureMockMvc
도 추가한다.
마지막 andExpert구문에 result ->를 추가해준다.
테스트 결과는 성공이지만
테스트 내용뒤에 .andDo(print())를 추가 하고 실행하면 상세 내용이 나타나게 된다.
테스트가 성공했으니 상세 내용까지 볼 필요는 없으므로 다시 지워준다.
@SpringBootTest는 실제 구동되는 애플리케이션의 설정, 모든 Bean을 로드하기 때문에 콘솔창을 확인해보면 리포지토리까지 실행되어서 hibernate 구문이 나타나는 것을 볼수 있다.
어떻게 보면 DB에 영향을 주는 테스트가 되어버리기 때문에 이를 위해서 @Transactional을 추가해준다.이렇게 해주면 테스트를 마무리 한뒤에 rollback을 해주기 때문에 DB에 영향을 주는 것을 막아준다. 해당 어노테이션은 같은 이름으로 javax와 spring 항목이 있는데 spring 쪽을 선택해서 작성한다.
다시 실행해보면 첫줄과 마지막줄에서 transaction 컨텍스트가 열리고 닫혀서 롤백이 진행되는 것을 알 수 있다.
이제 게시글 리스트 조회 뿐만 아니라, 게시글 단건, 게시글 -> 댓글 리스트 조회, 댓글 리스트 조회, 댓글 단건 조회 까지 테스트를 진행했다.
@DisplayName("[api] 게시글 단건 조회")
@Test
void GivenNothing_whenRequestingArticle_thenReturnsArticleJsonResponse() throws Exception {
// Given
// When & Then
mvc.perform(get("/api/articles/1"))
.andExpect(status().isOk())
.andExpect(result -> content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 게시글 -> 댓글 리스트 조회")
@Test
void GivenNothing_whenRequestingArticleCommentsFromArticle_thenReturnsArticleCommentsJsonResponse() throws Exception {
// Given
// When & Then
mvc.perform(get("/api/articles/1/articleComments"))
.andExpect(status().isOk())
.andExpect(result -> content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 댓글 리스트 조회")
@Test
void GivenNothing_whenRequestingArticleComments_thenReturnsArticleCommentsJsonResponse() throws Exception {
// Given
// When & Then
mvc.perform(get("/api/articleComments"))
.andExpect(status().isOk())
.andExpect(result -> content().contentType(MediaType.valueOf("application/hal+json")));
}
@DisplayName("[api] 댓글 단건 조회")
@Test
void GivenNothing_whenRequestingArticleComment_thenReturnsArticleCommentJsonResponse() throws Exception {
// Given
// When & Then
mvc.perform(get("/api/articleComments/1"))
.andExpect(status().isOk())
.andExpect(result -> content().contentType(MediaType.valueOf("application/hal+json")));
}
모두 성공!
변동사항을 푸시, pull request해서 main에 merge 해준다!