Spring RestDocs 문서화

이한수·2022년 7월 30일
2

Restful

목록 보기
2/2
post-thumbnail

공식문서를 참조하여 정리하였습니다.
개인 공부용도 목적입니다.

API 문서화

하이퍼링크

  • Spring REST Docs는 하이퍼미디어 기반 API에서 링크 문서화를 지원합니다.
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
		.andDo(document("index", links(
				linkWithRel("alpha").description("Link to the alpha resource"), 
				linkWithRel("bravo").description("Link to the bravo resource")))); 

1) HypermediaDocumentation.links 정적 메소드를 사용하여 , 링크를 문서화합니다.

2) HypermediaDocumentation.linkWithRel은 alpha인 링크를 예상합니다.

3) description은 그 링크에 대한 설명을 적습니다.

결과적으로 해당 서비스를 호출할 경우 ,기본 스니펫과 더불어, index라는 디렉토리안에 links.adoc 라는 스니펫이 추가 됩니다.

이때, 문서화 되지 않은 링크들이 발견되면 테스트가 실패합니다.

.andDo(document("index", links(halLinks(), 
		linkWithRel("alpha").description("Link to the alpha resource"),
		linkWithRel("bravo").description("Link to the bravo resource"))));

요청 및 응답

{
	"user": {
		"name": "Jane Doe",
		"email": "jane.doe@example.com"
	}
}

위와 같은 데이터를 요청하고 응답받는다 가정할 때,

요청 데이터의 경우

	 requestFields(
     		   fieldWithPath("user.name").description("사용자 이름"),
               fieldWithPath("user.email").description("사용자 이메일")
     )
    

응답 데이터의 경우

	 responseFields(
     		   fieldWithPath("user.name").description("사용자 이름"),
               fieldWithPath("user.email").description("사용자 이메일")
     )

각각 request-fields.adoc , response-fields.adoc가 생성됩니다.

이 또한 모든 필드를 문서화하지 않을 경우, 테스트는 실패합니다.

모든 필드에 문서화를 제공하고 싶지 않은 경우

1)subsectionWithPath

responseFields(
				subsectionWithPath("user").description("The user's info"))));

위와 같이 진행하면, user.name과 user.email이 문서화 된것으로 간주됩니다.

2)relaxedRequestFields , relaxedResponseFields

  • 특정 필드에 대한 문서화를 진행하지 않아도 테스트가 실패하지 않습니다.

그 밖의 필드 처리

배열의 데이터를 문서화 할 때

{
	"a":{
		"b":[
			{
				"c":"one"
			},
			{
				"c":"two"
			},
			{
				"d":"three"
			}
		],
		"e.dot" : "four"
	}
}
  • b배열안의 데이터를 문서화 해준다고 가정할 때, c라는 공통된 필드가 무수히 많을 경우 모두 문서화해줄 필요는 없습니다.
a.b[].c
a.b[].d

위와 같이 참조하여 문서화를 작성하여 처리할 수 있습니다.

배열 자체를 문서화하고 싶다면,

a.b[] 

이렇게 참조하시면 됩니다.

와일드카드를 이용할 떄

{
	"users":{
		"ab12cd34":{
			"role": "Administrator"
		},
		"12ab34cd":{
			"role": "Guest"
		}
	}
}
	users.*.role 

위와 같은 경로로 참조하여 공통 작성할 수 있습니다.

요청 매개변수

this.mockMvc.perform(get("/users?page=2&per_page=100")) 
		.andExpect(status().isOk()).andDo(document("users", requestParameters(
				parameterWithName("page").description("The page to retrieve"), 
				parameterWithName("per_page").description("Entries per page") 
		)));

혹은 POST 요청 본문에 요청 매개변수를 양식 데이터로 보낼 경우.

this.mockMvc.perform(post("/users").param("username", "Tester")) 
		.andExpect(status().isCreated()).andDo(document("create-user",
				requestParameters(parameterWithName("username").description("The user's username"))));
  • request-parameters.adoc라는 스니펫이 생성됩니다.
  • 이 또한 모든 매개변수가 문서화 되지 않으면 실패합니다.
  • 일부만 문서화를 하고 싶다면 requestParameters 대신 relaxedRequestParameters를 사용하시면 됩니다.

경로 매개변수

this.mockMvc.perform(get("/locations/{latitude}/{longitude}", 51.5072, 0.1275)) 
		.andExpect(status().isOk()).andDo(document("locations", pathParameters(
				parameterWithName("latitude").description("The location's latitude"), 
				parameterWithName("longitude").description("The location's longitude") 
		)));
  • path-parameters.adoc 라는 스니펫이 생성됩니다.

  • 모든 경로 변수가 문서화 되지 않을 경우, 테스트가 실패합니다.

  • 모든 경로 변수를 문서화하기 원치 않으신다면, relaxedPathParameters를 사용하시면 됩니다.

주의 : MockMvc를 사용하는 경우, 경로 매개변수를 문서화 하고자 한다면 , httpMethod를 MockMvcRequestBuilders대신에 RestDocumentationRequestBuilders로 변경해야 합니다.

파일 데이터 문서화

requestPart

this.mockMvc.perform(multipart("/upload").file("file", "example".getBytes())) 
		.andExpect(status().isOk()).andDo(document("upload", requestParts(
				partWithName("file").description("The file to upload")) 
		));
  • post 요청으로 수행합니다.
  • request-parts.adoc라는 스니펫이 생성됩니다.

-이또한 모든 데이터의 문서화가 요구되며 , 하지 않으실 경우, relaxedRequestParts를 이용하시면 됩니다.

requestPartBody

MockMultipartFile image = new MockMultipartFile("image", "image.png", "image/png", "<<png data>>".getBytes());
MockMultipartFile metadata = new MockMultipartFile("metadata", "", "application/json",
		"{ \"version\": \"1.0\"}".getBytes());

this.mockMvc.perform(multipart("/images").file(image).file(metadata).accept(MediaType.APPLICATION_JSON))
		.andExpect(status().isOk()).andDo(document("image-upload", requestPartBody("metadata"))); 

requestPartFields

MockMultipartFile image = new MockMultipartFile("image", "image.png", "image/png", "<<png data>>".getBytes());
MockMultipartFile metadata = new MockMultipartFile("metadata", "", "application/json",
		"{ \"version\": \"1.0\"}".getBytes());

this.mockMvc.perform(multipart("/images").file(image).file(metadata).accept(MediaType.APPLICATION_JSON))
		.andExpect(status().isOk()).andDo(document("image-upload", requestPartFields("metadata", 
				fieldWithPath("version").description("The version of the image")))); 
  • json으로 넘어가는 데이터의 필드를 문서화할 수 있습니다.

HTTP 헤더

this.mockMvc.perform(get("/people").header("Authorization", "Basic dXNlcjpzZWNyZXQ=")) 
		.andExpect(status().isOk()).andDo(document("headers", requestHeaders(
				headerWithName("Authorization").description("Basic auth credentials")), 
				responseHeaders(
						headerWithName("X-RateLimit-Limit")
								.description("The total number of requests permitted per period"),
						headerWithName("X-RateLimit-Remaining")
								.description("Remaining requests permitted in current period"),
						headerWithName("X-RateLimit-Reset")
								.description("Time at which the rate limit period will reset"))));

스니펫 재사용

  • 반복되는 문서화 요소를 재사용할 수 있습니다.
    먼저 공통요소를 설명하는 항목을 만듭니다.
protected final LinksSnippet pagingLinks = links(
		linkWithRel("first").optional().description("The first page of results"),
		linkWithRel("last").optional().description("The last page of results"),
		linkWithRel("next").optional().description("The next page of results"),
		linkWithRel("prev").optional().description("The previous page of results"));

그리고 이것을 사용할 때는 ,

this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
		.andDo(document("example", this.pagingLinks.and(
				linkWithRel("alpha").description("Link to the alpha resource"),
				linkWithRel("bravo").description("Link to the bravo resource"))))

-and 연산자를 이용하여 특정 문서화 요소를 추가할 수 있습니다.

profile
성실하게

0개의 댓글