본 프로젝트는 “스프링부트 3 백엔드 개발자 되기” 서적을 참고하여 진행하였음
블로그의 모든 글 조회하는 API 구현
•
BlogService.java
package com.example.msblog.service;
import com.example.msblog.domain.Article;
import com.example.msblog.dto.AddArticleRequest;
import com.example.msblog.repository.BlogRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@RequiredArgsConstructor // final이 붙거나 @NotNull이 붙은 필드의 생성자 추가
@Service // 빈으로 등록
public class BlogService {
private final BlogRepository blogRepository;
// 블로그 글 추가 메서드
public Article save(AddArticleRequest request) {
return blogRepository.save(request.toEntity());
}
// 모든 글 조회
public List<Article> findAll() {
return blogRepository.findAll();
}
}
Java
복사
응답을 위한 DTO 생성
•
ArticleResponse.java
package com.example.msblog.service;
import com.example.msblog.domain.Article;
import com.example.msblog.dto.AddArticleRequest;
import com.example.msblog.repository.BlogRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@RequiredArgsConstructor // final이 붙거나 @NotNull이 붙은 필드의 생성자 추가
@Service // 빈으로 등록
public class BlogService {
private final BlogRepository blogRepository;
// 블로그 글 추가 메서드
public Article save(AddArticleRequest request) {
return blogRepository.save(request.toEntity());
}
// 모든 글 조회
public List<Article> findAll() {
return blogRepository.findAll();
}
}
Java
복사
전체 글을 조회한 뒤 반환
•
BlogApiController.java
package com.example.msblog.controller;
import com.example.msblog.domain.Article;
import com.example.msblog.dto.AddArticleRequest;
import com.example.msblog.dto.ArticleResponse;
import com.example.msblog.service.BlogService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RequiredArgsConstructor
@RestController // HTTP RESPONSE BODY에 객체 데이터를 JSON 형태로 반환
public class BlogApiController {
private final BlogService blogService;
// HTTP 메서드가 POST일 때 전달받은 URL과 동일하면 메서드로 매핑
@PostMapping("/api/articles")
// @RequestBody로 요청 본문 값 매핑
public ResponseEntity<Article> addArticle(@RequestBody AddArticleRequest request) {
Article savedArticle = blogService.save(request);
// 요청한 자원이 성공적으로 생성되었으며 저장된 블로그 글 정보를 응답 객체에 담아 전송
return ResponseEntity.status(HttpStatus.CREATED)
.body(savedArticle);
}
// 전체 글을 조회한 뒤 반환하는 findAllArticles() 메서드 추가
// /api/articles GET 요청이 오면 글 전체를 조회하는 findAll() 메서드 호출한 다음
// 응답용 객체인 ArticleResponse로 파싱해 body에 담아 클라이언트에게 전송
// stream: 여러 데이터가 모여 있는 컬렉션을 간편하게 처리하기 위한 기능
@GetMapping("/api/articles")
public ResponseEntity<List<ArticleResponse>> findAllArticles() {
List<ArticleResponse> articles = blogService.findAll()
.stream()
.map(ArticleResponse::new)
.toList();
return ResponseEntity.ok().body(articles);
}
}
Java
복사
테스트를 위한 sql 파일 생성
•
쿼리 작성
INSERT INTO article (title, content) VALUES ('제목 1', '내용 1')
INSERT INTO article (title, content) VALUES ('제목 2', '내용 2')
INSERT INTO article (title, content) VALUES ('제목 3', '내용 3')
SQL
복사
•
Postman 테스트 결과
블로그 글 전체 조회 위한 테스트 코드 작성
•
given-when-then
Given | When | Then |
블로그 글 저장 | 목록 조회 API 호출 | 응답 코드가 200 OK 이고 반환받은 값 중에 0번째 요소의 content와 title이 저장된 값과 같은지 확인 |
•
BlogApiControllerTest
@DisplayName("findAllAritcles: 블로그 글 목록 조회에 성공한다.")
@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));
}
Java
복사
블로그 글 하나를 조회하기 위한 서비스, 컨트롤러 구현
•
BlogService.java
// 블로그 글 하나를 조회, 조회 후 글이 없으면 예외 처리
public Article findById(long id) {
return blogRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found: " + id));
}
Java
복사
•
BlogApiController.java
// @PathVariable => URL에서 값을 가져오는 애너테이션
// /api/articles/3 GET 요청 받을 시 id에 3이 들어옴
// findById() 메서드로 넘어가 3번 블로그 글을 찾음
@GetMapping("/api/articles/{id}")
// URL 경로에서 값 추출
public ResponseEntity<ArticleResponse> findArticle(@PathVariable long id) {
Article article = blogService.findById(id);
return ResponseEntity.ok().body(new ArticleResponse(article));
}
Java
복사
블로그 글 하나 조회하기 위한 테스트 코드 작성
•
given-when-then
Given | When | Then |
블로그 글 저장 | 저장한 블로그 글의 id값으로 API 호출 | 응답 코드가 200 OK 이고 반환받은 content와 title이 저장된 값과 같은지 확인 |
•
BlogApiControllerTest
@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));
}
Java
복사