나의 에러 일지

Spring - "urlTemplate not found. If you are using MockMvc did you use RestDocumentationRequestBuilders to build the request?" 원인과 해결 방법

Cold Bean 2023. 5. 30. 18:32
728x90

배경

이번 에러는 RestDocs를 생성하기 위한 통합 테스트 중 api에 path parameter를 문서화하는 과정에서 발생한 에러다.

아래는 에러가 발생했던 테스트 코드이다. 

@Slf4j
@Disabled
@Transactional
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs
@ActiveProfiles("test")
public class BaseIntegrationTest {
    @Autowired
    protected MockMvc mvc;

    @Autowired
    protected Gson gson;
}
@Slf4j
class FeedIntegrationTest extends BaseIntegrationTest {

    private final String BASE_URL = "/feeds";

    ...

    @Test
    @DisplayName("피드 조회")
    void feedControllerTest2() throws Exception {
        // given
        CustomUserDetails userDetails = StubData.MockMember.getUserDetails();
        TokenDto tokenDto = jwtTokenProvider.generateTokenDto(userDetails);
        String accessToken = tokenDto.getAccessToken();
        String refreshToken = tokenDto.getRefreshToken();
        String encryptedRefreshToken = aes128Config.encryptAes(refreshToken);

        // when
        String uri = BASE_URL + "/{feed-id}";
        ResultActions actions = ResultActionsUtils.getRequestWithTokenAndPathVariable(
                mvc, uri, feedId, accessToken, encryptedRefreshToken);

        // then
        FeedDto.Response response = ObjectMapperUtils.actionsSingleToResponseWithData(
                actions, FeedDto.Response.class);
        assertThat(response.getId()).isNotNull();
        assertThat(response.getContents()).isNotNull();
        assertThat(response.getNickname()).isNotNull();
        assertThat(response.getTags()).isNotNull();
        actions
                .andExpect(status().isOk())
                .andDo(document("find-feed",
                        getRequestPreProcessor(),
                        getResponsePreProcessor(),
                        RequestSnippet.getTokenSnippet(),
                        RequestSnippet.getFeedPathVariableSnippet(),
                        ResponseSnippet.getFeedSnippet()));
    }
public static ResultActions getRequestWithTokenAndPathVariable(MockMvc mockMvc,
                                                               String url,
                                                               long feedId,
                                                               String accessToken,
                                                               String encryptedRefreshToken) throws Exception {
    return mockMvc.perform(get(url, feedId)  // 여기서 예외 발생
                    .contentType(MediaType.APPLICATION_JSON)
                    .header(AUTHORIZATION_HEADER, BEARER_PREFIX + accessToken)
                    .header(REFRESH_HEADER, encryptedRefreshToken))
            .andDo(print());
}
java.lang.IllegalArgumentException: urlTemplate not found. If you are using MockMvc did you use RestDocumentationRequestBuilders to build the request?

	at org.springframework.util.Assert.notNull(Assert.java:201)
	at org.springframework.restdocs.request.PathParametersSnippet.extractUrlTemplate(PathParametersSnippet.java:126)
	at org.springframework.restdocs.request.PathParametersSnippet.extractActualParameters(PathParametersSnippet.java:113)
	at org.springframework.restdocs.request.AbstractParametersSnippet.verifyParameterDescriptors(AbstractParametersSnippet.java:89)
	at org.springframework.restdocs.request.AbstractParametersSnippet.createModel(AbstractParametersSnippet.java:74)
	at org.springframework.restdocs.request.PathParametersSnippet.createModel(PathParametersSnippet.java:98)
	at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:78)
	at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:191)
	at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:52)
	at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:219)
	at com.frog.travelwithme.intergration.feed.FeedIntegrationTest.feedControllerTest2(FeedIntegrationTest.java:178)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	...

 

원인

에러 내용을 번역해보면 UrlTemplate을 찾을 수 없으며, MockMvc로 요청했을 때 RestDocumentationRequestBuilders를 사용하고 있는지 묻고 있다. 

 

공식 문서를 찾아보면 RestDocumentationRequestBuilders는 MockMvcRequestBuilders를 확장한 클래스이며 pathParameters를 문서화할 때 필요하다고 한다. 

 

해결

예외에서 알려준대로 MockMvcRequestBuilders의 get메서드를 사용하던 코드를 RestDocumentationRequestBuilders를 사용하도록 수정했다. 

public static ResultActions getRequestWithTokenAndPathVariable(MockMvc mockMvc,
                                                               String url,
                                                               long feedId,
                                                               String accessToken,
                                                               String encryptedRefreshToken) throws Exception {
    return mockMvc.perform(RestDocumentationRequestBuilders.get(url, feedId)  // RestDocumentationRequestBuilders를 사용하도록 변경
                    .contentType(MediaType.APPLICATION_JSON)
                    .header(AUTHORIZATION_HEADER, BEARER_PREFIX + accessToken)
                    .header(REFRESH_HEADER, encryptedRefreshToken))
            .andDo(print());
}

에러 없이 잘 실행된다!

 

728x90