완벽한 장면 2023. 10. 13. 22:15

블로그 글 목록 조회 API 구현하기

1. 서비스 코드 구현

BlogService - findAll() 추가

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

    private final BlogRepository blogRepository;

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

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

만들었으면, 요청을 받아 글 목록을 조회할 컨트롤러 작성

2. 컨트롤러 코드 작성하기

1) DTO 구현

dto.response.ArticleResponse

@Getter
public class ArticleResponse {

    private final String title;
    private final String content;

    public ArticleResponse(Article article) {
        this.title = article.getTitle();
        this.content = article.getContent();
    }
}

 

2) 컨트롤러 구현

controller.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);
    }

}

 


실행 테스트 Postman

data.sql 생성하여 샘플 데이터 3개 추가

INSERT INTO article (title, content) VALUES ('제목1', '내용1')
INSERT INTO article (title, content) VALUES ('제목2', '내용2')
INSERT INTO article (title, content) VALUES ('제목3', '내용3')

 

실행하기

3개 잘 나옴을 알 수 있음.

 

 

테스트 코드 작성

개요

- findAll() 테스트 코드

BlogApiController

@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("findAllArticles: 블로그 글 목록 조회에 성공한다.")
    @Test
    public void findAllArticles() throws Exception {
        // given
        final String url = "/api/articles";
        final String title = "title";
        final String content = "content";

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

        // when
        final ResultActions resultActions = mockMvc.perform(get(url)
                .accept(MediaType.APPLICATION_JSON));

        // then
        resultActions
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].content").value(content))
                .andExpect(jsonPath("$[0].title").value(title));
    }

}

 

 

 


 

블로그 글 단일 조회 API 구현하기

1. 서비스 코드 구현

BlogService - findById() 추가

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

    private final BlogRepository blogRepository;

    // 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));
    }

}

 


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));
    }

}

 


테스트 코드 작성하기

개요

@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 findAllArticles() throws Exception {
        // given
        final String url = "/api/articles";
        final String title = "title";
        final String content = "content";

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

        // when
        final ResultActions resultActions = mockMvc.perform(get(url)
                .accept(MediaType.APPLICATION_JSON));

        // then
        resultActions
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].content").value(content))
                .andExpect(jsonPath("$[0].title").value(title));
    }



    @DisplayName("findArticle: 블로그 글 조회 성공.")
    @Test
    public void findArticle() 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
        final ResultActions resultActions = mockMvc.perform(get(url, savedArticle.getId()));

        // then
        resultActions
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content").value(content))
                .andExpect(jsonPath("$.title").value(title));
    }

}

 

 

 

728x90
반응형