2022.11.16 (수요일)

yeonicerely·2022년 11월 16일
0

1. 알고리즘

2. 테스트 코드 작성해보기

A. 테스트 코드를 작성하는 이유

(1) deploy 하기 전에 테스트 단계에서 오류를 잡을 수 있다.
(2) 테스트를 할 수 있게 코드를 짜기 위해서 - 테스트를 할 수 있는 코드는 구조가 좋다
(3) 테스트 코드를 보는 것만으로도 코드가 어떻게 동작하는지 이해하기가 쉽다.

B. 테스트 코드 작성하기

1) 슬라이스 테스트

  • Controller와 같이 외부의 요인을 차단하고 테스트를 진행할 수 없는 경우(단위 테스트)에는 레이어 별로(presentation 계층 - Controller| 비지니스/서비스 계층 - Service | 데이터 접근 계층 - DAO or Repository) 테스트를 진행할 수 있는데, 이를 슬라이스 테스트라고 한다.

2) 컨트롤러 테스트 코드 작성하기

(1) @WebMvcTest: Controller를 테스트할 때 사용하는 annotation. 이 때 테스트하고자 하는 클래스를 명시해주지 않으면 @Controller, @RestController 등 컨트롤러와 관련된 bean 객체를 호출한다.

(2) @MockBean: 가짜 객체를 생성하도록 한다. Controller는 서비스 계층에 의존되어 있다. 따라서 Service 객체 대신에 가짜 객체를 생성하여 Service 객체의 역할을 대신 하도록 한다.
- Mockito의 given() 메서드를 이용해 가짜 객체에서 어떤 메서드가 호출되고 어떤 파라미터를 주입할 수 있는지를 설정할 수 있다.
- willReturn() 메서드를 통해 어떤 결과를 리턴할 것인지를 정할 수 있다.

(3) MockMvc: 서블릿 컨테이너를 구동하지 않고(웹 사이트를 띄우지 않고) 가상 환경에 모의로 url 요청을 보내서 컨트롤러가 제대로 작동하는지 테스트할 수 있도록 해준다.

  • 정보를 조회하는 get() 메소드 테스트 코드
@WebMvcTest(ArticleRestController.class) 
class ArticleRestControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper objectMapper;

    @MockBean
    ArticleService articleService;

    @Test
    @DisplayName("reponse가 잘 오는지 확인")
    void test1() throws Exception {
        ArticleResponse articleResponse = ArticleResponse.builder()
                .id(1L)
                .content("첫번째게시글입니다")
                .title("1번")
                .build();

        given(articleService.getArticle((long) 1))
                .willReturn(articleResponse);
        // 가짜 객체가 articleService의 getArticle() 메소드를 호출해서 id를 넣어주면 
        // articleResponse를 결과로 return하도록 한다.

        long articleId = 1;

        String url = String.format("/api/v1/articles/%d", articleId);
        
        // perform() 메서드는 MockMvcRequestBuilders에서 제공하는 메서드를 이용해서 http 요청정보를 설정할 수 있다.
        mockMvc.perform(get(url)) 
                .andExpect(status().isOk()) // andExpect를 통해서 결과값을 검증할 수 있다.
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.title").value("1번"))
                .andExpect(jsonPath("$.content").value("첫번째게시글입니다"))
                .andDo(print()); // andDo() 메서드를 이용해서 요청과 응답의 전체 내용을 확인할 수 있다.

        verify(articleService).getArticle(articleId);
        // 메서드가 잘 실행되었는지 검증하는 역할
        // default가 1, 뒤에 숫자를 넣어주면 몇 번 실행되었는지를 검증할 수 있다.

    }
    
    ...

}
  • RequestBody에서 받은 정보를 추가하는 addArticle() 메소드 테스트 코드

(1) post 요청할 때 @RequestBody의 값을 넘겨주기 위해 content()에 DTO의 값을 담아준다.
이 때 RequestBody는 보통 json 파일의 형태이므로 ObjectMapper의 writeValueAsByte()를 이용하거나 Gson의 toJson()을 이용해서 넘겨줄 수 있다.

@WebMvcTest(ArticleRestController.class)
class ArticleRestControllerTest {

...

    @Test
    @DisplayName("데이터를 잘 생성하는지 확인")
    void test2() throws Exception {
        ArticleAddRequest articleAddRequest = new ArticleAddRequest("제목", "내용");

        given(articleService.addArticle(articleAddRequest))
                .willReturn(new ArticleAddResponse(1L, articleAddRequest.getTitle(), articleAddRequest.getContent()));
        mockMvc.perform(post("/api/v1/articles/add")
                        .content(objectMapper.writeValueAsBytes(articleAddRequest))

                        .contentType(MediaType.APPLICATION_JSON))
                       
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").exists())
                .andExpect(jsonPath("$.title").value("제목"))
                .andExpect(jsonPath("$.content").value("내용"))
                .andDo(print());

        verify(articleService).addArticle(articleAddRequest);
        // articleService가 1번 이상 호출되었는지?


    }

}

  • Gson을 이용해서 넘겨주는 경우
		Gson gson = new Gson();

        mockMvc.perform(post("/api/v1/articles/add")
                        .content(gson.toJson(articleAddRequest))

                        .contentType(MediaType.APPLICATION_JSON))
                        ...
                        

참고자료

  1. 스프링 부트 핵심가이드, 장정우, pp.157~183

0개의 댓글