포스트

프로젝트:샐로그 / 테스트 - 수입 1 : 컨트롤러 슬라이스 테스트 (Gson 커스텀)


개요

이번에는 수입 파트다.

회원 쪽에서 많은 내용을 작성했고, 해당 포스트만 봐도 테스트 케이스를 어떻게 작성해야할지 알 수는 있기 때문에 수입 부분에서는 특별한 내용이 있지 않은 한 작성하지 않을 생각이다.


그렇기 때문에 굉장히 짧거나 작성하지 않을 수 있다.


그런데 수입 쪽에서 컨트롤러 슬라이스 테스트를 진행하던 중 특이사항이 있기 때문에 이번 포스트를 작성한다.




수입 컨트롤러 슬라이스 테스트

앞선 회원 컨트롤러 슬라이스 테스트와 마찬가지로 “통신”이 잘 되는 지에 중점을 두고 테스트 케이스를 작성했다.

이를 위해 원하는 값으로 요청을 보내고서 예상된 응답 코드가 돌아오는 지 확인하면 된다.

전체적인 흐름을 보아야하는 것 아닌가라고 생각할 수 있지만 애플리케이션 통합 테스트를 별도로 진행할 예정이고, 슬라이스 테스트는 빠르고 간결하게 동작하는 지 파악하는 테스트이기 때문에 간단하게 진행했다.


먼저 말하자면, 수입 /post 엔드포인트로의 요청을 제외하면 나머지는 회원 쪽과 거의 동일하다.

수입 post도 대부분 비슷하지만 한 가지 유의해야할 것이 있기 때문에 작성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    @Test
    @DisplayName("/post")
    @Order(1)
    void postIncomeTest() throws Exception {
        // Given
        LocalDate date = LocalDate.of(2024, 1, 1);
        IncomeDto.Post post = new IncomeDto.Post(100, "testName", "testMemo", date, "testTag");

        // LocalDate 커스텀 직렬화
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
                .create();

        String content = gson.toJson(post);

        // When
        mockMvc.perform(
                post("/income/post")
                        .header("Authorization", "Bearer fakeToken")
                        .accept(MediaType.APPLICATION_JSON)
                        .contentType(MediaType.APPLICATION_JSON)
                        .characterEncoding("UTF-8")
                        .content(content)
                )

                // Then
                .andExpect(status().isCreated())
                .andDo(print());
    }

이게 수입 등록에 대한 테스트 케이스다.

중간을 보면 gson을 커스텀 직렬화 했다고 되어 있는데, 회원 쪽과 동일하게 진행하면서 문제가 발생해 정의된 내용이다.


커스텀 직렬화 부분을 제외하면 post DTO에 요청 바디를 넣고 /income/post 엔드포인트로 요청을 해보는 방식이다.

여기서 문제는 date다.

date는 타입 자체가 LocalDate 타입이기 때문에 실제로 요청 시 json 형태로 “2024-01-01”로 요청을 보내게 된다.

그러나 현재 테스트 케이스는 java로 작성이 되기 때문에 문법에 맞게 초기화 후 인스턴스화 해야 했다.

여기까지 진행한 후 테스트를 실행해 보니 응답 코드가 400이었고, 어드바이스로 정의해놓은 에러코드를 뱉어냈다.


이 이유를 찾기 위해 andDo(print()) 로 출력된 결과를 살펴봤지만, 바디가 인코딩 되지 않았다는 정보와 함께 작성한 바디가 아예 보이지 않았다.

그래서 요청 시 UTF-8 인코딩을 적용하게 되었다.


이후 다시 실행시켜보니 바디에 담긴 date가

“date” : “2024-01-01” 형태가 아닌 “date” : {“year” : 2024, “month” : 1, “day” : 1} 이런 형태로 출력되었다.

이를 바탕으로 postDto를 json으로 직렬화 해주는 gson을 활용하여 해결할 수 있는 방법은 없는지 구글링 해보았고,
쏘니의 개발블로그 여기서 해결법을 찾을 수 있었다.

그렇게 커스텀 생성을 위해 정의한 코드가 위 내용이며,

1
2
3
4
5
6
    private static class LocalDateSerializer implements JsonSerializer<LocalDate> {
        @Override
        public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src.format(DateTimeFormatter.ISO_LOCAL_DATE));
        }
    }

LocalDateSerializer 클래스를 활용해 날짜에 대한 포맷을 커스텀 했다.


이를 통해 문제를 해결할 수 있었고, 테스트는 정상적으로 통과했다.





후기

사실 처음에는 바디 인코딩을 어떤 식으로 해야할지에 대해 찾느라 헤맸고, gson을 어떻게 수정할 수 있을 지에 대해서도 많이 헤맸다.

이외에도 요청 uri를 잘못 입력해서 거의 1시간 가량을 헤맸다.


그래도 이런 시행착오를 통해 gson을 커스텀해 원하는 형태로 직렬화 할 수 있다는 것을 알게 되었고, 테스트 시 한결 편하게 수행 가능할 것 같다.

이 블로그는 저작권자의 CC BY 4.0 라이센스를 따릅니다.