이전에는 기존에 저장되어있던 DB에서 데이터를 JSON형식으로 출력하는 방식을 했었다. 이에 이번에는 JSON형식으로 받아와 JSON형식으로 출력하는 방식을 구현해보도록 하겠다.
@Entity
@Table(name = "article2")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
public Article(String title,String content) {
this.title = title;
this.content = content;
}
// ArticleEntity를 ArticleAddResponse DTO로 만들어주는 부분
public static ArticleAddResponse of2(Article article) {
return new ArticleAddResponse(article.getId(),
article.getTitle(),article.getContent());
}
}
@AllArgsConstructor
@Getter
@EqualsAndHashCode
public class ArticleAddRequest {
private String title;
private String content;
// 사용자에게 값을 입력받아 Entity로 변환함
// 이때 생성자 대신 Builder를 통해 좀 더 확실히 맵핑하여 데이터 전송함
public Article toEntity(){
Article article = Article.builder()
.title(this.title)
.content(this.content)
.build();
return article;
}
}
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ArticleAddResponse {
private Long id;
private String title;
private String content;
}
@RestController
@RequestMapping("/api/v1/articles")
public class ArticleRestContorller {
private final ArticleRestService articleRestService;
public ArticleRestContorller(ArticleRestService articleRestService) {
this.articleRestService = articleRestService;
}
@GetMapping("/{id}")
public ResponseEntity<ArticleAddResponse> getfind(@PathVariable Long id){
return ResponseEntity.ok().body(articleRestService.getfind(id));
}
@PostMapping
public ResponseEntity<ArticleAddResponse> addArticle(@RequestBody ArticleAddRequest dto) { // @RequestBody를 통해 json 형식으로 받음
ArticleAddResponse response = articleRestService.add(dto);
return ResponseEntity.ok().body(response);
}
}
RestController를 통해 Json형식으로 데이터를 주고 받는다고 정의
ResponseEntity를 통해 Json형식으로 구현가능
isOk() - 상태 코드가 200인지 확인
isNotFount() - 상태 코드가 404인지 확인
isMethodNotAllowed() - 상태 코드가 405인지 확인
isInternalServerError() - 상태 코드가 500인지 확인
is(int status) - 몇 번 응답 상태 코드가 설정되었는지 확인 ex) is(200), is(404)
GetMapping에서는 DB에 저장된 데이터를 Json으로 반환해주는 기능을 함
PostMapping에서는 사용자가 Json형식으로 데이터를 보내면 @RequsetBody를 통해 ArticleAddRequest DTO에 저장하고 Entity로 변환 후 DB에 저장함
@Service
public class ArticleRestService {
private final ArticleRepository articleRepository;
public ArticleRestService(ArticleRepository articleRepository) {
this.articleRepository = articleRepository;
}
public ArticleAddResponse getfind(Long id){
Optional<Article> optarticle = articleRepository.findById(id);
Article article = optarticle.get();
ArticleAddResponse articleDto = Article.of2(article);
return articleDto;
}
public ArticleAddResponse add(ArticleAddRequest dto){
Article article = dto.toEntity();
Article savedArticle = articleRepository.save(article);
return new ArticleAddResponse(savedArticle.getId(), savedArticle.getTitle(), savedArticle.getContent());
}
}
@Repository
public interface ArticleRepository extends JpaRepository<Article, Long> {
}
@WebMvcTest(ArticleRestContorller.class) // Test할 Controller 클래스 지정
class ArticleRestContorllerTest {
@Autowired
MockMvc mockMvc; // MockMvc를 의존받음
@Autowired
ObjectMapper objectMapper; // json 형식으로 변환하기 위해 사용하는 라이브러리
@MockBean // 가짜 객체
ArticleRestService articleRestService;
@Test
@DisplayName("글 등록이 잘 되는지 확인")
// json 형식으로 값 입력받아 저장되는지 확인
void add() throws Exception {
ArticleAddRequest dto = new ArticleAddRequest("제목입니다.","내용입니다.");
ArticleAddResponse resp = new ArticleAddResponse(1l,dto.getTitle(),dto.getContent());
// 가짜 객체로 현재 여기서 any를 통해 articleRestService는 어떤값을 받아도 무조건 resp를 반환한다.
// (service 테스트내용) -> given을 통해 service에 들어가는 객체와 출력되는 객체를 지정하고
// verify를 통해 service 메서드의 실행결과 확인함
given(articleRestService.add(any()))
.willReturn(resp);
// controller 테스트 내용
mockMvc.perform(post("/api/v1/articles")
.contentType(MediaType.APPLICATION_JSON) // Json 타입으로 사용
.content(objectMapper.writeValueAsBytes(dto)) // 삽입한 데이터 dto를 json 형식으로 변환
)
// 입력된 데이터와 예측되는 값을 비교함
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").exists()) // 존재여부 확인
.andExpect(jsonPath("$.title").exists())
.andExpect(jsonPath("$.title").value("제목입니다."))
.andExpect(jsonPath("$.content").exists())
.andDo(print());
verify(articleRestService).add(dto); // service의 add 메서드가 실행됬는지 확인함
// service의 테스트 결과 확인
}
}
❓ ObjectMapper란?
JSON 컨텐츠를 Java 객체로 deserialization 하거나 Java 객체를 JSON으로 serialization 할 때 사용하는 Jackson 라이브러리의 클래스이다.
ObjectMapper는 생성 비용이 비싸기 때문에 bean/static으로 처리하는 것이 좋다.
Jackson 라이브러리에 관한 내용은 더 공부하고 나중에 따로 작성해보도록 하겠다.