이전 포스팅에서 이어집니다!
✨ 블로그 기획하고 API 만들기 (1) ✨
(생략)
// 데이터베이스에 저장되어 있는 모든 글을 가져오는 메소드
public List<Article> findAll(){
return blogRepository.findAll();
}
package me.ansoohyeon.springbootdeveloper.dto;
import lombok.Getter;
import me.ansoohyeon.springbootdeveloper.domain.Article;
@Getter
public class ArticleResponse {
private final String title;
private final String content;
public ArticleResponse(Article article){
this.title = article.getTitle();
this.content = article.getContent();
}
}
(생략)
@GetMapping("/api/articles")
public ResponseEntity<List<ArticleResponse>> findAllArticles(){
List<ArticleResponse> articles = blogService.findAll()
.stream()
.map(ArticleResponse::new)
.toList();
return ResponseEntity.ok()
.body(articles);
}
INSERT INTO article (title, content) VALUES ('제목 1', '내용 1')
INSERT INTO article (title, content) VALUES ('제목 2', '내용 2')
INSERT INTO article (title, content) VALUES ('제목 3', '내용 3')
그리고 포스트맨으로 데이터를 조회해 보면 INSERT가 제대로 된 모습이다!
(생략)
@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));
}
테스트 성공!
(생략)
// 데이터베이스에 저장되어 있는 글 하나 가져오는 메소드
public Article findById(long id){
return blogRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("not found : " + id));
}
(생략)
@GetMapping("/api/articles/{id}")
// URL 경로에서 값 추출
public ResponseEntity<ArticleResponse> findArticle(@PathVariable long id){
Article article = blogService.findById(id);
return ResponseEntity.ok()
.body(new ArticleResponse(article));
}
(생략)
@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));
}
역시나 테스트 성공! 👍
(생략)
// 블로그 글 삭제 메소드
public void delete(long id){
blogRepository.deleteById(id);
}
(생략)
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Void> deleteArticle(@PathVariable long id){
blogService.delete(id);
return ResponseEntity.ok()
.build();
}
포스트맨으로 Delete 실행 후 get을 실행하면 정말로 삭제가 된 모습이다! 이 부분은 간단하니 생략하도록 하겠다.
(생략)
@DisplayName("deleteArticle : 블로그 글 삭제에 성공한다.")
@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();
}
삭제까지 모두 테스트 성공이다. 😉
드디어 마지막... 수정이다..!
(생략)
public void update(String title, String content){
this.title = title;
this.content = content;
}
package me.ansoohyeon.springbootdeveloper.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class UpdateArticleRequest {
private String title;
private String content;
}
// 블로그 글 수정 메소드
@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;
}
(생략)
@PutMapping("/api/articles/{id}")
public ResponseEntity<Article> updateArticle(@PathVariable long id, @RequestBody UpdateArticleRequest request){
Article updateArticle = blogService.update(id, request);
return ResponseEntity.ok()
.body(updateArticle);
}
이 부분도 생략하겠다!
(생략)
@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);
}
이렇게 모든 기능의 테스트를 성공했다!
스프링 부트를 사용해서 CRUD를 작성하는 방법과 테스트 코드를 작성하는 방법을 예제와 함께 살펴보았다. CRUD는 모든 기능의 기반이 되는 기능이고 이번에 작성한 코드 또한 프로젝트 진행 시 가장 기초적인 모델이므로 익숙해지는 것이 중요하겠다. ✨