티스토리 뷰

블로그 글 삭제 API 구현하기

1. 서비스 메서드 코드

BlogService

@RequiredArgsConstructor // final이 붙거나 @NotNull이 붙은 필드의 생성자 추가
@Service
public class BlogService {

    private final BlogRepository blogRepository;

    // 게시글을 작성한 유저인지 확인
    private static void authorizeArticleAuthor(Article article) {
        // 현재 사용자 이름을 가져와 게시물의 작성자와 비교하고, 다른 경우에 예외 던짐
        String userName = SecurityContextHolder.getContext().getAuthentication().getName();
        if (!article.getAuthor().equals(userName)) {
            throw new IllegalArgumentException("not authorized");
        }
    }

    // AddArticleRequest를 사용하여 새 게시물을 생성하고,
    // 지정된 사용자 이름으로 게시물을 저장
    public Article save(AddArticleRequest request, String username) {
        return blogRepository.save(request.toEntity(username));
    }

    // 블로그 리포지토리를 통해 모든 게시물을 조회하여 반환
    public List<Article> findAll() {
        return blogRepository.findAll();
    }

    // 주어진 'id'로 게시물을 조회하고, 게시물이 없으면 예외 던짐
    public Article findById(Long id) {
        return blogRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("not fonund: " + id));
    }
    
    @Transactional
    public Article update(Long id, UpdateArticleRequest request) {
        // 주어진 'id'로 게시물을 조회하고, 게시물이 없으면 예외 던짐
        Article article = blogRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("not found: " + id));

        // 게시물의 작성자를 확인하고, 작성자와 현재 사용자가 다르면 예외 던짐
        authorizeArticleAuthor(article);
        // 게시물의 내용을 업데이트하고 업데이트된 게시물을 반환
        article.update(request.getTitle(), request.getContent());

        return article;
    }

    
    // 추가
    
    // 주어진 'id'로 게시물을 조회하고, 게시물이 없으면 예외 던짐
    public void delete(long id) {
        Article article = blogRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("not found : " + id));

        // 게시물의 작성자를 확인하고, 작성자와 현재 사용자가 다르면 예외 던짐
        authorizeArticleAuthor(article);
        // 게시물 삭제
        blogRepository.delete(article);
    }
}

2. 컨트롤러 메서드 코드

BlogApiController

@RequiredArgsConstructor
@RestController // HTTP Response Body에 객체 데이터를 JSON 형식으로 반환하는 컨트롤러
public class BlogApiController {

    private final BlogService blogService;


    @PostMapping("/api/articles")
    //요청 본문 값 매핑
    // HTTP POST 요청을 처리하여 블로그 글을 추가.
    public ResponseEntity<Article> addArticle(@RequestBody AddArticleRequest request, Principal principal) {
        Article savedArticle = blogService.save(request, principal.getName());
        // 요청한 자원이 성공적으로 생성되었으며 저장된 블로그 글 정보를 응답 객체에 담아 전송
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(savedArticle);
    }

    @GetMapping("/api/articles")
    public ResponseEntity<List<ArticleResponse>> findAllArticles() {
        // 블로그 서비스를 통해 모든 게시물을 조회하고, 각 게시물을 ArticleResponse로 매핑
        List<ArticleResponse> articles = blogService.findAll()
                .stream()
                .map(ArticleResponse::new)
                .toList();

        // 조회된 게시물 목록을 ResponseEntity로 래핑하여 반환
        return ResponseEntity.ok()
                .body(articles);
    }

    @GetMapping("/api/articles/{id}")
    // URL 경로에서 'id' 값을 추출하여 메서드의 매개변수로 사용
    public ResponseEntity<ArticleResponse> findArticle(@PathVariable Long id) {

        // 주어진 'id'로 블로그 서비스를 통해 게시물을 조회
        Article article = blogService.findById(id);
        // 조회된 게시물을 ArticleResponse로 매핑하고 ResponseEntity로 래핑하여 반환
        return ResponseEntity.ok()
                .body(new ArticleResponse(article));
    }


    @PutMapping("/api/articles/{id}")
    public ResponseEntity<Article> updateArticle(@PathVariable Long id,
                                                 @RequestBody UpdateArticleRequest request) {
        // 주어진 'id'로 블로그 서비스를 통해 게시물을 업데이트하고 업데이트된 게시물을 받음
        Article updatedArticle = blogService.update(id, request);

        // 업데이트된 게시물을 ResponseEntity로 래핑하여 반환
        return ResponseEntity.ok()
                .body(updatedArticle);
    }
    
    
    
    //추가
    
    @DeleteMapping("/api/articles/{id}")
    public ResponseEntity<Void> deleteArticle(@PathVariable Long id) {
        // 주어진 'id'로 블로그 서비스를 통해 게시물을 삭제
        blogService.delete(id);
        // 삭제 성공을 나타내는 ResponseEntity를 반환
        return ResponseEntity.ok()
                .build();
    }
}

실행 테스트하기

처음 3개 글 있는 것에서

1

 

첫 번째 글을 삭제해보고 

2

 

다시 전체조회하면

3

 

삭제 완료됨을 확인 가능

 

 

 


테스트 코드 작성하기

개요

@SpringBootTest
@AutoConfigureMockMvc
class BlogApiControllerTest {

    @Autowired
    protected MockMvc mockMvc;

    @Autowired
    protected ObjectMapper objectMapper;

    @Autowired
    private WebApplicationContext context;

    @Autowired
    BlogRepository blogRepository;

    @BeforeEach
    public void mockMvcSetUp() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .build();
        blogRepository.deleteAll();
    }


    @DisplayName("블로그 글 삭제 성공.")
    @Test
    public void deleteArticle() 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());

        // when
        mockMvc.perform(delete(url, savedArticle.getId()))
                .andExpect(status().isOk());

        // then
        List<Article> articles = blogRepository.findAll();

        assertThat(articles).isEmpty();
    }

}
728x90
반응형
Comments
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
250x250