ใํ ์คํธ ์ฝ๋ & Spring REST Docsใ
๊ฐ์ธ ํ๋ก์ ํธ๋ ์์ฑ์ด ๋์๋ค. ์ด์ ๋ ์ธ๋ถ์ ์ธ ๋ํ ์ผ์ ์ ๊ฒฝ์ ์ฐ๋ฉฐ ๋ฆฌํฉํฐ๋ง๊ณผ ๊ทธ์ ํ์ํ ๊ฐ๋ ์ ๋ฆฌ๋ฅผ ํ๋ฉฐ ํ๋ก์ ํธ์ ์ ์ฉ์ํค๊ณ ์๋ค.
REST API๋ฅผ ์ฒ์ ์ค๊ณํด ๋ณด์๋๋ฐ, ๋ถ์กฑํ ์ ์ด ๋ง์์ง๋ง ์ ์ ํ ๊ฒฝํ์ด๊ณ ์งง์ ๊ธฐ๊ฐ ๋ด์ ๋ฐฐ์ด ๊ฒ์ด ๋ง์ ์ค๊ณ ๊ณผ์ ์ด์๋ค.
API๋ฅผ ์ค๊ณํ๋ฉด ๊ทธ์ ๋ง๋ ๋ช ์ธ๊ฐ ํ์ํ๋ฐ, ๋ณดํต Swagger๋ Spring REST Docs ํ๋ ์์ํฌ๋ฅผ ์ด์ฉํ๋ค๊ณ ํ๋ค.
Swagger๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๋ ธํ ์ด์ ์ ์ด์ฉํด ํธํ๊ฒ ๋ฌธ์๋ฅผ ์์ฑํ ์ ์์ง๋ง, ํ๋ก์ ํธ์ ํ์ค์ฑ๊ณผ ์ ํ์ฑ์ ๋ท๋ฐ์นจํ๊ธฐ ์ํด์๋ ํ ์คํธ ์ฝ๋ ์์ฑ์ด ํ์๋ผ๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ Spring REST Docs๋ฅผ ์ด์ฉํ๊ธฐ๋ก ์๊ฐํ๋ฉฐ ์ ์ฉํด๋ณด์๋ค.
ํ ์คํธ ์ฝ๋
ํฌ๊ฒ ๋จ์ ํ ์คํธ์ ํตํฉ ํ ์คํธ๊ฐ ์๋ค.
ํตํฉ ํ ์คํธ
๋จ์ ํ ์คํธ๋ณด๋ค ๋ ํฐ ๋์์ ๋ฌ์ฑํ๊ธฐ ์ํด ์ฌ๋ฌ ๋ชจ๋๋ค์ ๋ชจ์ ์๋๋๋ก ํ๋ ตํ๋์ง ํ์ธํ๋ ํ ์คํธ
์ฃผ๋ก @SpringBootTest ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ํตํฉ ํ ์คํธ ํ๊ฒฝ์ ์์ฑํ๋ค.
๋จ์ ํ ์คํธ
๊ฐ๋ฅํ ๊ฐ์ฅ ์์ ์ํํธ ์จ์ด๋ฅผ ์คํํ์ฌ ์์๋๋ก ๋์ํ๋์ง ํ์ธํ๋ ํ ์คํธ
=> TDD ์งํ ์ ์ ์ฉํ๋ค
์๋ฐ๋ ์ฃผ๋ก Junit์ ์ฌ์ฉํ์ฌ ํ ์คํธํ๋ค.
๋์ ๊ฒฝ์ฐ๋ ์คํ๋ง ํ๋ก์ ํธ์ด๋ฏ๋ก ์์กด์ฑ์ ํ ์คํธ ๋ชจ๋์ด ์๋ ์ถ๊ฐ ๋์์ผ๋ฏ๋ก ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด ๋๋ค.
testImplementation 'org.springframework.boot:spring-boot-starter-test'
์ฌ๊ธฐ์ Mock Object๋ฅผ ์ด์ฉํ Mockito Framework๋ฅผ ์ด์ฉํ์ฌ ๋จ์ ํ ์คํธ๋ฅผ ์งํํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
๊ทธ์ค ์ปจํธ๋กค๋ฌ์ ๋จ์ ํ ์คํธ๋ฅผ ์งํํ๊ธฐ๋ก ํ๋ค.
์ฌ์ฉํ๋ ์ ๋ ธํ ์ด์ ์ @WebMVCTest๊ณผ @AutoConfigureRestDocs๋ฅผ ์ด์ฉํ์ฌ Spring REST Docs๋ฅผ ๋์์ ์งํํ๋ค.
User API ํ ์คํธ
@BeforeEach
public void setUp(RestDocumentationContextProvider restDocumentationContextProvider) {
mockMvc =
MockMvcBuilders.standaloneSetup(new UserController(userService))
.apply(documentationConfiguration(restDocumentationContextProvider))
.addFilters(new CharacterEncodingFilter("utf-8", true))
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
.build();
}
@Test
@DisplayName("ํ์ ๋ํ
์ผ ์กฐํ ํ
์คํธ")
void detailActionTest() throws Exception {
Mockito.when(userService.findById(userDTO.getUserId())).thenReturn(userDTO);
this.mockMvc
.perform(get("/api/users/{userId}", userDTO.getUserId()).accept(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer ${AUTH_TOKEN}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.userId", is(userDTO.getUserId())))
.andExpect(jsonPath("$.data.userMainAddress", is(userDTO.getUserMainAddress())))
.andExpect(jsonPath("$.message", is("๊ถํ : BASIC_USER")))
.andDo(document("detailUser", preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint())))
;
}
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
@WebMvcTest(UserController.class)
@Import(value = {AuthorizationExtractor.class, JwtTokenProvider.class})
@AutoConfigureRestDocs
class UserControllerTest {
ํ ์คํธ ํด๋์ค์ ๋ถ์ธ ์ ๋ ธํ ์ด์ ๋ค
ํ ์คํธ๊ฐ ์๋ฃ ๋๋ฉด snipets ํ์ผ๋ค์ด ์์ฑ๋๋ค. ์ด๋ฅผ ํตํด ๋ฌธ์ํํ ์ ์๋ค.
์ด๋ ๊ฒ ์์ฑ์ด ๋จ.
.adoc ํ์ผ์ ํตํด ๋ฌธ์๋ฅผ ์์ฑํ ์ ์๋ค. ์ด๋ ์๊น ์์ฑ๋ snippets ํ์ผ๋ค์ ์ฝ์ ํด ์์ฑ ๊ฐ๋ฅํ๋ค.
๊ฐ๋จํ ์ด๊ธฐ ๋ฒ์ ์ ์์ฑํ๋ค.
์ด์ ์ฅ๋ฐ๊ตฌ๋, ์ฃผ๋ฌธ, ๊ด๋ฆฌ์ API๋ฅผ ์ถ๊ฐํด์ผ๊ฒ ๋ค.