From 75f2f96838cb8f3545d5d6b97787f5b54b2b6a6c Mon Sep 17 00:00:00 2001 From: tlarbals824 Date: Sun, 27 Aug 2023 21:48:46 +0900 Subject: [PATCH 1/3] =?UTF-8?q?PET-80=20chore=20:=20RestDocs=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Auth-Module/build.gradle | 2 + Common-Module/Test-Module/build.gradle | 0 .../pawith/testmodule/BaseRestDocsTest.java | 39 ++++++++++++++++ .../com/pawith/testmodule/RestDocsConfig.java | 20 ++++++++ build.gradle | 46 ++++++++++++------- settings.gradle | 4 +- 6 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 Common-Module/Test-Module/build.gradle create mode 100644 Common-Module/Test-Module/src/main/java/com/pawith/testmodule/BaseRestDocsTest.java create mode 100644 Common-Module/Test-Module/src/main/java/com/pawith/testmodule/RestDocsConfig.java diff --git a/Auth-Module/build.gradle b/Auth-Module/build.gradle index 41be1c3e..a50511fb 100644 --- a/Auth-Module/build.gradle +++ b/Auth-Module/build.gradle @@ -1,6 +1,8 @@ subprojects { dependencies { implementation project(":Common-Module") + testImplementation project(":Common-Module:Test-Module") + // spring security implementation "org.springframework.boot:spring-boot-starter-security" diff --git a/Common-Module/Test-Module/build.gradle b/Common-Module/Test-Module/build.gradle new file mode 100644 index 00000000..e69de29b diff --git a/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/BaseRestDocsTest.java b/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/BaseRestDocsTest.java new file mode 100644 index 00000000..006b6678 --- /dev/null +++ b/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/BaseRestDocsTest.java @@ -0,0 +1,39 @@ +package com.pawith.testmodule; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.context.annotation.Import; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; + +@AutoConfigureRestDocs +@Import({RestDocsConfig.class}) +@ExtendWith(RestDocumentationExtension.class) +public class BaseRestDocsTest { + + @Autowired + protected RestDocumentationResultHandler resultHandler; + + protected MockMvc mvc; + + @BeforeEach + void setUp(final WebApplicationContext applicationContext, + final RestDocumentationContextProvider provider){ + this.mvc = MockMvcBuilders.webAppContextSetup(applicationContext) + .apply(MockMvcRestDocumentation.documentationConfiguration(provider).uris().withPort(8080)) + .alwaysDo(MockMvcResultHandlers.print()) + .alwaysDo(resultHandler) + .addFilters(new CharacterEncodingFilter("UTF-8", true)) + .build(); + } + +} diff --git a/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/RestDocsConfig.java b/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/RestDocsConfig.java new file mode 100644 index 00000000..8f0ea92c --- /dev/null +++ b/Common-Module/Test-Module/src/main/java/com/pawith/testmodule/RestDocsConfig.java @@ -0,0 +1,20 @@ +package com.pawith.testmodule; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.operation.preprocess.Preprocessors; + +@TestConfiguration +public class RestDocsConfig{ + + @Bean + public RestDocumentationResultHandler restDocumentationResultHandler(){ + return MockMvcRestDocumentation.document( + "{class-name}/{method-name}", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()) + ); + } +} diff --git a/build.gradle b/build.gradle index 83e5f5ea..b1ace9a6 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ allprojects { repositories { mavenCentral() } + } springBoot { @@ -32,9 +33,16 @@ subprojects { bootJar.enabled=true } + configurations { + compileOnly { + extendsFrom annotationProcessor + } + asciidoctorExtensions + } + dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-test' // jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' @@ -50,34 +58,38 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok' // restdocs - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor' + implementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // Fixture testing tool testImplementation("com.navercorp.fixturemonkey:fixture-monkey-starter:0.6.3") } - - configurations { - compileOnly { - extendsFrom annotationProcessor - } + // RestDocs 설정 + ext { + snippetsDir = file('build/generated-snippets') } - repositories { - mavenCentral() + test { + useJUnitPlatform() + outputs.dir snippetsDir } - ext { - set('snippetsDir', file("build/generated-snippets")) + asciidoctor { + dependsOn test + configurations 'asciidoctorExtensions' + inputs.dir snippetsDir + + baseDirFollowsSourceFile() } - tasks.named('test') { - outputs.dir snippetsDir - useJUnitPlatform() + tasks.register("asciidoctorToApiModule", Copy){ + dependsOn asciidoctor + from file("build/docs/asciidoc/") + into rootProject.file("Api-Module/src/main/resources/static/docs") } - tasks.named('asciidoctor') { - inputs.dir snippetsDir - dependsOn test + build{ + dependsOn asciidoctorToApiModule } } diff --git a/settings.gradle b/settings.gradle index be8cc281..1bab0f8d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,6 +24,4 @@ include 'Domain-Module:User-Module:user-application' findProject('Domain-Module:User-Module:user-application')?.name = 'user-application' include 'Common-Module' -include 'Domain-Module:User-Module:user-application:test' -findProject(':Domain-Module:User-Module:user-application:test')?.name = 'test' - +include 'Common-Module:Test-Module' \ No newline at end of file From a3c9687936a157ee86312f6d549217f20da3b6b6 Mon Sep 17 00:00:00 2001 From: tlarbals824 Date: Sun, 27 Aug 2023 21:49:43 +0900 Subject: [PATCH 2/3] =?UTF-8?q?PET-80=20test=20:=20OAuthController=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?Auth-API.adoc=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/static/docs/Auth-API.html | 590 ++++++++++++++++++ .../src/docs/asciidoc/Auth-API.adoc | 7 + .../adaptor/api/OAuthControllerTest.java | 71 +++ .../api/TestSpringBootApplicationConfig.java | 7 + 4 files changed, 675 insertions(+) create mode 100644 Api-Module/src/main/resources/static/docs/Auth-API.html create mode 100644 Auth-Module/auth-adaptor/src/docs/asciidoc/Auth-API.adoc create mode 100644 Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/OAuthControllerTest.java create mode 100644 Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/TestSpringBootApplicationConfig.java diff --git a/Api-Module/src/main/resources/static/docs/Auth-API.html b/Api-Module/src/main/resources/static/docs/Auth-API.html new file mode 100644 index 00000000..2d92baee --- /dev/null +++ b/Api-Module/src/main/resources/static/docs/Auth-API.html @@ -0,0 +1,590 @@ + + + + + + + +Auth-API + + + + + +
+
+

Auth-API

+
+
+

Auth 소셜 로그인

+
+

Curl request

+
+
+
$ curl 'http://localhost:8080/oauth/KAKAO?accessToken=%E4%8E%A9%C9%BD%E1%9D%84%E8%B4%98%ED%83%A3%EB%B8%9C%DB%A2%E2%A3%A1%E7%85%92%E4%88%BE%E6%BC%B5%E9%A3%8B%E4%93%82%E5%A7%8E%E3%9A%9B%E7%A5%B9%E6%B2%BA%E1%AB%AB%E9%9D%92%E8%B0%9A%E7%A4%94%EB%9A%B0%E3%8F%9D%E8%A0%87%E6%A8%8C%E4%96%B5%ED%95%A4' -i -X GET
+
+
+
+
+

HTTP request

+
+
+
GET /oauth/KAKAO?accessToken=%E4%8E%A9%C9%BD%E1%9D%84%E8%B4%98%ED%83%A3%EB%B8%9C%DB%A2%E2%A3%A1%E7%85%92%E4%88%BE%E6%BC%B5%E9%A3%8B%E4%93%82%E5%A7%8E%E3%9A%9B%E7%A5%B9%E6%B2%BA%E1%AB%AB%E9%9D%92%E8%B0%9A%E7%A4%94%EB%9A%B0%E3%8F%9D%E8%A0%87%E6%A8%8C%E4%96%B5%ED%95%A4 HTTP/1.1
+Host: localhost:8080
+
+
+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 115
+
+{
+  "accessToken" : "캰즠ﹳ썆㋰ﭸ䢌봁ꗡ踺嗏矀瑰⡄횵龹᫝藠렼∶ᨄ晹",
+  "refreshToken" : null
+}
+
+
+
+
+

HTTPie request

+
+
+
$ http GET 'http://localhost:8080/oauth/KAKAO?accessToken=%E4%8E%A9%C9%BD%E1%9D%84%E8%B4%98%ED%83%A3%EB%B8%9C%DB%A2%E2%A3%A1%E7%85%92%E4%88%BE%E6%BC%B5%E9%A3%8B%E4%93%82%E5%A7%8E%E3%9A%9B%E7%A5%B9%E6%B2%BA%E1%AB%AB%E9%9D%92%E8%B0%9A%E7%A4%94%EB%9A%B0%E3%8F%9D%E8%A0%87%E6%A8%8C%E4%96%B5%ED%95%A4'
+
+
+
+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /oauth/{provider}
ParameterDescription

provider

OAuth 제공자

+
+
+

Request body

+
+
+
+
+
+
+
+

Request parameters

+ ++++ + + + + + + + + + + + + +
ParameterDescription

accessToken

OAuth 접근 토큰

+
+
+

Response body

+
+
+
{
+  "accessToken" : "캰즠ﹳ썆㋰ﭸ䢌봁ꗡ踺嗏矀瑰⡄횵龹᫝藠렼∶ᨄ晹",
+  "refreshToken" : null
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

accessToken

String

access 토큰

refreshToken

Null

refresh 토큰

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/Auth-Module/auth-adaptor/src/docs/asciidoc/Auth-API.adoc b/Auth-Module/auth-adaptor/src/docs/asciidoc/Auth-API.adoc new file mode 100644 index 00000000..effc7d8f --- /dev/null +++ b/Auth-Module/auth-adaptor/src/docs/asciidoc/Auth-API.adoc @@ -0,0 +1,7 @@ +[[Auth-API]] +== Auth-API + +[[Auth-소셜로그인]] +=== Auth 소셜 로그인 + +operation::o-auth-controller-test/o-auth-login[snippents='http-request.adoc,http-response.adoc'] \ No newline at end of file diff --git a/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/OAuthControllerTest.java b/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/OAuthControllerTest.java new file mode 100644 index 00000000..8d76b789 --- /dev/null +++ b/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/OAuthControllerTest.java @@ -0,0 +1,71 @@ +package com.pawith.authmodule.adaptor.api; + +import com.navercorp.fixturemonkey.FixtureMonkey; +import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; +import com.pawith.authmodule.application.dto.OAuthResponse; +import com.pawith.authmodule.application.dto.Provider; +import com.pawith.authmodule.application.port.in.OAuthUseCase; +import com.pawith.testmodule.BaseRestDocsTest; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; + +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@Slf4j +@WebMvcTest(OAuthController.class) +@DisplayName("OAuthController 테스트") +class OAuthControllerTest extends BaseRestDocsTest { + + private static final String OAUTH_URL = "/oauth/{provider}"; + private static final String OAUTH_REQUEST_ACCESS_TOKEN_PARAM_NAME = "accessToken"; + + @MockBean + OAuthUseCase oAuthUseCase; + + @Test + @DisplayName("OAuth 로그인") + void oAuthLogin() throws Exception { + //given + final Provider testProvider = FixtureMonkey.create().giveMeOne(Provider.class); + final String OAUTH_ACCESS_TOKEN = FixtureMonkey.create().giveMeOne(String.class); + final OAuthResponse testOAuthResponse = getFixtureMonkey().giveMeOne(OAuthResponse.class); + MockHttpServletRequestBuilder request = get(OAUTH_URL, testProvider) + .param(OAUTH_REQUEST_ACCESS_TOKEN_PARAM_NAME, OAUTH_ACCESS_TOKEN); + given(oAuthUseCase.oAuthLogin(testProvider, OAUTH_ACCESS_TOKEN)).willReturn(testOAuthResponse); + //when + ResultActions result = mvc.perform(request); + //then + result.andExpect(status().isOk()) + .andDo(print()) + .andDo(resultHandler.document( + requestParameters( + parameterWithName(OAUTH_REQUEST_ACCESS_TOKEN_PARAM_NAME).description("OAuth 접근 토큰") + ), + pathParameters( + parameterWithName("provider").description("OAuth 제공자") + ), + responseFields( + fieldWithPath("accessToken").description("access 토큰"), + fieldWithPath("refreshToken").description("refresh 토큰") + ) + )); + + } + + private FixtureMonkey getFixtureMonkey() { + return FixtureMonkey.builder() + .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) + .build(); + } +} \ No newline at end of file diff --git a/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/TestSpringBootApplicationConfig.java b/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/TestSpringBootApplicationConfig.java new file mode 100644 index 00000000..2dce5d01 --- /dev/null +++ b/Auth-Module/auth-adaptor/src/test/java/com/pawith/authmodule/adaptor/api/TestSpringBootApplicationConfig.java @@ -0,0 +1,7 @@ +package com.pawith.authmodule.adaptor.api; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestSpringBootApplicationConfig { +} From 4ccba6d9d6484d210b23efce13df3339d1180757 Mon Sep 17 00:00:00 2001 From: tlarbals824 Date: Sun, 27 Aug 2023 21:50:20 +0900 Subject: [PATCH 3/3] =?UTF-8?q?PET-80=20feat=20:=20RestDocs=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20URI=20=ED=86=A0=ED=81=B0=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authmodule/application/common/consts/IgnoredPathConsts.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Auth-Module/auth-application/src/main/java/com/pawith/authmodule/application/common/consts/IgnoredPathConsts.java b/Auth-Module/auth-application/src/main/java/com/pawith/authmodule/application/common/consts/IgnoredPathConsts.java index d9d7cf35..8b7e644f 100644 --- a/Auth-Module/auth-application/src/main/java/com/pawith/authmodule/application/common/consts/IgnoredPathConsts.java +++ b/Auth-Module/auth-application/src/main/java/com/pawith/authmodule/application/common/consts/IgnoredPathConsts.java @@ -12,6 +12,7 @@ public class IgnoredPathConsts { @Getter private static Map ignoredPath = Map.of( + "/docs/**", HttpMethod.GET, "/oauth/**", HttpMethod.GET, "/jwt", HttpMethod.GET, "/actuator/**", HttpMethod.GET