백엔드/Spring Boot

6. 블로그 기획하고 API 만들기 (3) - 블로그 글 작성을 위한 API 구현❸

두개의 문 2023. 7. 31. 11:14

6. 블로그 글 삭제 API 구현하기 

◉ ID에 해당하는 블로그 글을 삭제하는 API 구현

 

1) 서비스 메서드 코드 작성하기 

 

◉ BlogService.java 파일에 delete() 메서드 추가 

    → JPA에서 제공하는 deleteById() 메서드 이용해 데이터베이스에서 데이터를 삭제함 

// 글 삭제 
public void deleteById(long id) {
    blogRepository.deleteById(id);
}

 


2) 컨트롤러 메서드 코드 작성하기 

 

◉ /api/articles/{id} DELETE 요청이 오면, {id}에 해당하는 값이 @PathVariable 애너테이션을 통해 들어옴

 

▪︎ BlogApiController.java 

// * 글 삭제하는 메서드 
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Void> deleteArticle(@PathVariable long id) {
    blogService.deleteById(id);

    return ResponseEntity.ok()
                .build();
}

 


3) 실행 테스트하기 

 

◉ 포스트맨에서  HTTP 메서드 : DELETE로 설정, URL : 'http://localhost/api/articles/1' 입력 → Send 클릭 

    ( 단, 반드시 스프링 부트 서버를 실행한 상태에서 진행해야 함 )

 

 - 삭제 후, 블로그 글을 조회하는 API에 요청을 전송 

   → ID가 1인 글은 삭제되고, 나머지 2개의 글만 보이는 것 확인 가능 

 

 

 - 만약 삭제한 글을 조회하는 요청을 전송할 경우, 사용자 정의 예외가 발생 

 


4) 테스트 코드 작성하기 

 

▪︎ BlogApiControllerTest.java

given 블로그 글을 저장함 
when  저장한 블로그 글의 id값으로 삭제 API를 호출함 
then 응답 코드가 200 Ok이고, 블로그 글 리스트를 전체 조회해 조회한 배열 크기가 0인지 확인함 

 

@DisplayName("deleteArticle : 블로그 글 삭제에 성공한다.")
@Test 
public void deleteArticle() throws Exception{

    // * given
    final String url = "/api/articles/{id}";
    final String title = "title";
    final String content = "content";

    // 삭제 여부를 알기 위해 일단 기존 자료는 @BeforeEach 모드로 삭제됨 
    // 여기서는 레코드 하나를 추가하고 when 블럭에서 삭제할 계획 
    Article savedArticle = blogRepository.save(Article.builder()
            .title(title)
            .content(content)
            .build());

    // * when
    // DELETE 메서드 요청을 만들어 냄 
    // : 테스트를 위해 만든 한 개의 글을 삭제 
    mockMvc.perform(delete(url, savedArticle.getId()))
                .andExpect(status().isOk());

    // * then
    // : 전체 리스트 조회하여 비어있는지 확인 
    List<Article> articles = blogRepository.findAll();

    assertThat(articles).isEmpty();

}​

 

 

 


 

7. 블로그 글 수정 API 구현하기 

1) 서비스 메서드 코드 작성하기 

 

 

① Article.java 파일에 엔티티에 요청받은 내용으로 값을 수정하는 update() 메서드 추가 

// * 수정하는 메서드 
//   : @Getter만 사용해서 읽기만 가능하게 만들었기 때문에
//     CRUD에서 U(update)가 불가능하게 되어 할 수 없이 추가됨 
//     ( ∵ @Setter가 없기 때문에 수정 불가 ) 
public void update(String title, String content) {
    this.title = title;
    this.content = content;
}

 

 

② 블로그 글 수정 요청을 받은 DTO 작성 

 

◎ dto 디렉토리에 UpdateArticleRequest.java 파일을 생성 

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class UpdateArticleRequest {
	private String title;
	private String content;
}

 

 

③ BlogService.java 파일을 열어 리포지터리를 사용해 글을 수정하는 update() 메서드 추가 

// * 글 수정하는 메서드 
@Transactional
public Article update(long id, UpdateArticleRequest request) {
    Article article = blogRepository.findById(id)
            .orElseThrow(() -> new IllegalArgumentException("not found : " + id));

    article.update(request.getTitle(), request.getContent());

    return article;
}

▪︎ @Transitional 애너테이션 

  - 매칭한 메서드를 하나의 트랜잭션으로 묶는 역할 

  - 스프링에서는 트랙잭션을 사용하기 위해 다른 작업할 필요없이 이 애너테이션만 사용하면 됨 

 

 


2) 컨트롤러 메서드 코드 작성하기 

 

◉ /api/articles/{id} PUT 요청이 오면, 글을 수정하기 위한 updateArticle() 메서드 작성 

 

// * 블로그 글 수정 요청 시 
@PutMapping("/api/articles/{id}")
// /api/articles/{id} PUT 요청 시, Request Body 정보가 request로 넘어옴 
public ResponseEntity<Article> updateArticle(@PathVariable long id,
        @RequestBody UpdateArticleRequest request){

    Article updatedArticle = blogService.update(id, request);
    // 다시 서비스 클래스의 update() 메서드에 id와 request를 넘겨줌

    return ResponseEntity.ok()
            .body(updatedArticle);
    // 응답 값은 body에 담아 전송함 
}

 

 


3) 실행 테스트하기 

 

◉ 포스트맨에서  HTTP 메서드 : PUT로 설정, URL : 'http://localhost/api/articles/1' 입력 

     → 수정 내용은 [ Body ] 탭을 사용, 입력을 마친 후 SEND 클릭 

 

 

 

 


4) 테스트 코드 작성하기 

 

▪︎ BlogApiControllerTest.java

given 블로그 글을 저장하고, 블로그 글 수정에 필요한 요청 객체를 만듦
when  UPDATE API로 수정 요청을 보냄. 이때 요청 타입은 JSON이며, given 절에서 미리 만들어둔 객체를 요청 본문으로 함께 보냄 
then 응답 코드가 200 Ok인지 확인함. 블로그 글 id로 조회한 후에 값이 수정되었는지 확인

 

@DisplayName("updateArticle : 블로그 글 수정에 성공한다.")
@Test
public void updateArticle() throws Exception {
    // * given
    final String url = "/api/articles/{id}";
    final String title = "title";
    final String content = "content";

    Article savedArticle = blogRepository.save(Article.builder()
                    .title(title)
                    .content(content)
                    .build());

    final String newTitle = "new title";
    final String newContent = "new content";

    UpdateArticleRequest request = new UpdateArticleRequest(newTitle, newContent);

    // * when
    ResultActions result = mockMvc.perform(put(url, savedArticle.getId())
            .contentType(MediaType.APPLICATION_JSON_VALUE)
            .content(objectMapper.writeValueAsString(request)));

    //* then
    result.andExpect(status().isOk());

    Article article = blogRepository.findById(savedArticle.getId()).get();

    assertThat(article.getTitle()).isEqualTo(newTitle);
    assertThat(article.getContent()).isEqualTo(newContent);
}