Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
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 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[Server] Controller Test 본문

Project/대중교통 길찾기

[Server] Controller Test

Seung__ 2022. 1. 23. 23:40

1. 문제 현상


현재 api결과를 view로 넘겨주고, view에서 조회할 때 에러가 발생한다.

result - pathLIst - path - SubPathList - subPath 의 구조로 이루어져있는데, 

th:each를 통해 pathList에서 path를 반복해서 꺼내고, 각 path에서 th:each를 통해 subPathList에서 subPath를 꺼낸 뒤 값을 조회한다.

 

이때 에러가 발생하는 부분은 subpath의 필드값을 조회하는 부분이다. 이 부분에서 nullPointerException이 발생.

<div id="paths">
    <div th:each="path : ${result.pathList}" class="accordion-item">
        <h2 class="accordion-header" id="headingOne">
            <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
                <table>
                    <tr>
                        <b><td th:text="${path.totalTime}+분"><b>소요시간(분) </b></td></b>
                    </tr>
                    <tr>
                        <td th:text="${path.totalDistance}+m">이동거리(미터)</td>
                    </tr>
                </table>
            </button>
        </h2>
        <div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
            <div class="accordion-body" th:object="${path}" th:with="subPathList=${path.subPathList}">
                <table class="table table-striped" >
                    <tr th:each="subPath : ${subPathList}">
                        <li th:text="${subPath.toString()}"></li>
                        <tr>
                            <span th:text="${subPath?.trafficType}?:'데이터 없음'"></span>
                            <li th:object="${subpath}"  th:if="${subPath?.trafficType} == 3" th:text="|${subPath?.sectionTime}분|">도보 이동거리</li>
                        </tr>
                        <tr>
                             <span th:text="${subPath?.trafficType}?:'데이터 없음'"></span>
                            <li th:object="${subpath}"  th:if="${subPath?.trafficType} == 2" th:text="|${subPath?.startName}정류장 ${subPath.lane.busNo}번 승차|">버스탑승</li>
                        </tr>
                        <tr>
                             <span th:text="${subPath?.trafficType}?:'데이터 없음'"></span>
                            <li th:object="${subpath}"  th:if="${subPath?.trafficType} == 2" th:text="|${subPath?.endName}정류장 하차|">버스하차</li>
                        </tr>
                        <tr>
                             <span th:text="${subPath?.trafficType}?:'데이터 없음'"></span>
                            <li th:object="${subpath}"  th:if="${subPath?.trafficType} == 1" th:text="|${subPath?.startName} 역 ${subPath.lane.name}호선 승차|">지하철 승차</li>
                        </tr>
                        <tr>
                             <span th:text="${subPath?.trafficType}?:'데이터 없음'"></span>
                            <li th:object="${subpath}"  th:if="${subPath?.trafficType} == 1" th:text="|${subPath?.endName}역 하차|">지하철 하차</li>
                        </tr>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</div>

 

디버깅을 해보면 model에 subPath의 값들을 정상적으로 들어가있다. 

 

 

2. Test Code


일단 model -> view의 과정에서 문제가 없음을 확인하기 위해 테스트를 해보자.

@SpringBootTest
@AutoConfigureMockMvc
class ApiControllerTest {

    @Autowired OdSayClient odSayClient;
    @Autowired MockMvc mockMvc;

    @Test
    @DisplayName("SubPath의 필드값 확인")
    void searchRoute() throws Exception {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("SX","126.9707979959352");
        params.add("SY","37.5547020732267");
        params.add("EX","127.10012275846414");
        params.add("EY","37.513264531390575");

        ModelAndView mav;
        mav = mockMvc.perform(MockMvcRequestBuilders.post("/search")
                .params(params)
                .contentType(MediaType.APPLICATION_JSON))
                .andReturn().getModelAndView();

        assert mav != null;
        SearchRouteRes result = (SearchRouteRes) mav.getModel().get("result");
        Path path = result.getPathList().get(0);
        SubPath subPath = path.getSubPathList().get(0);

        //subPath 의 필드값을 출력.
        System.out.println("subPath_trafficType : " + subPath.getTrafficType());
        assertThat(subPath.getTrafficType()).isEqualTo(3);
    }
}

일반적으로 Controller의 slice test를 위해서는 @WebMvcTest() @AutoConfigureWebMvc의 조합을 사용한다.

 

만약 MockMVC를 사용하며 full application test를 하고싶으면, @SpringBootTest와 @AutoConfigurationMockMvc의 조합을 사용하면 된다.

If you are looking to load your full application configuration and use MockMVC, you should consider @SpringBootTest combined with @AutoConfigureMockMvc rather than this annotation.

 

Test는 의도한 것 과 같이 잘 동작했다.

[request api] uri = https://api.odsay.com/v1/api/searchPubTransPathT?SX=126.9707979959352&SY=37.5547020732267&EX=127.10012275846414&EY=37.513264531390575&apiKey=key
result class : class java.lang.String
subPath_trafficType : 3

model에 담긴 값이 null이 아니다.

 

 

3. 결론


view에서 subPath의 필드값을 조회하는 부분이 문제.

1) th:each 중첩이 안되나?

2) 타임리프 문법 오류

Comments