From b112698cf013172fe363b4c89f30b46c04f9f056 Mon Sep 17 00:00:00 2001 From: dev_kong Date: Wed, 4 Oct 2023 22:56:38 +0900 Subject: [PATCH 01/10] test: controller test context load 9->1 --- .../controller/AuthControllerTest.java | 10 --- .../controller/BaseControllerTest.java | 29 +++++++-- .../controller/CafeAdminControllerTest.java | 12 ++-- .../controller/CafeControllerTest.java | 64 ++++++++++--------- .../controller/LikedCafeControllerTest.java | 45 ++++++------- .../controller/LocationControllerTest.java | 4 -- .../controller/LoginArgumentResolverTest.java | 25 ++------ 7 files changed, 91 insertions(+), 98 deletions(-) diff --git a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java index e303f516..ef5ca3bd 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java @@ -23,16 +23,12 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpStatus; import com.project.yozmcafe.controller.auth.OAuthProvider; import com.project.yozmcafe.domain.member.Member; import com.project.yozmcafe.domain.member.MemberInfo; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.service.auth.GoogleOAuthClient; import com.project.yozmcafe.service.auth.JwtTokenProvider; -import com.project.yozmcafe.service.auth.KakaoOAuthClient; import io.restassured.http.Cookie; import io.restassured.matcher.DetailedCookieMatcher; @@ -41,12 +37,6 @@ class AuthControllerTest extends BaseControllerTest { - @SpyBean - GoogleOAuthClient googleOAuthClient; - @SpyBean - KakaoOAuthClient kakaoOAuthClient; - @SpyBean - MemberRepository memberRepository; @Autowired JwtTokenProvider jwtTokenProvider; diff --git a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java index fea6f2e4..9f229d57 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java @@ -1,18 +1,26 @@ package com.project.yozmcafe.controller; -import com.project.yozmcafe.BaseTest; -import io.restassured.RestAssured; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.specification.RequestSpecification; +import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; -import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; +import com.project.yozmcafe.BaseTest; +import com.project.yozmcafe.domain.S3Client; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.service.auth.GoogleOAuthClient; +import com.project.yozmcafe.service.auth.JwtTokenProvider; +import com.project.yozmcafe.service.auth.KakaoOAuthClient; + +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.specification.RequestSpecification; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @ExtendWith(RestDocumentationExtension.class) @@ -20,6 +28,17 @@ public abstract class BaseControllerTest extends BaseTest { @LocalServerPort private int port; + @SpyBean + protected GoogleOAuthClient googleOAuthClient; + @SpyBean + protected KakaoOAuthClient kakaoOAuthClient; + @SpyBean + protected MemberRepository memberRepository; + @SpyBean + protected S3Client s3Client; + @SpyBean + protected JwtTokenProvider jwtTokenProvider; + protected RequestSpecification spec; @BeforeEach diff --git a/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java index 085c9424..941ab7a0 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java @@ -25,9 +25,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; -import org.springframework.mock.web.MockMultipartFile; +import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.databind.ObjectMapper; import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; @@ -35,15 +34,12 @@ import com.project.yozmcafe.controller.dto.cafe.CafeRequest; import com.project.yozmcafe.controller.dto.cafe.CafeUpdateRequest; import com.project.yozmcafe.controller.dto.cafe.DetailRequest; -import com.project.yozmcafe.domain.S3Client; import com.project.yozmcafe.domain.cafe.available.Days; class CafeAdminControllerTest extends BaseControllerTest { @Autowired private ObjectMapper mapper; - @MockBean - private S3Client s3Client; private File image = new File("src/test/resources/image.png"); @@ -51,7 +47,7 @@ class CafeAdminControllerTest extends BaseControllerTest { @DisplayName("카페 저장하기") void save() { //given - doNothing().when(s3Client).upload(any(MockMultipartFile.class)); + doNothing().when(s3Client).upload(any(MultipartFile.class)); final String cafeRequestJson = makeCafeRequest(); //when, then @@ -74,7 +70,7 @@ void save() { @DisplayName("카페 업데이트") void update() { //given - doNothing().when(s3Client).upload(any(MockMultipartFile.class)); + doNothing().when(s3Client).upload(any(MultipartFile.class)); doNothing().when(s3Client).delete(anyString()); String location = saveCafe(); String updateRequest = makeCafeUpdateRequest(); @@ -202,7 +198,7 @@ void saveCoordinate() { } private String saveCafe() { - doNothing().when(s3Client).upload(any(MockMultipartFile.class)); + doNothing().when(s3Client).upload(any(MultipartFile.class)); final String cafeRequest = makeCafeRequest(); final String location = given().log().all() diff --git a/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java index 09ba3a7d..b6ecb0d8 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java @@ -1,27 +1,5 @@ package com.project.yozmcafe.controller; -import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse; -import com.project.yozmcafe.controller.dto.cafe.CafeResponse; -import com.project.yozmcafe.controller.dto.cafe.CafeSearchResponse; -import com.project.yozmcafe.domain.cafe.Cafe; -import com.project.yozmcafe.domain.cafe.CafeRepository; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.domain.menu.MenuRepository; -import com.project.yozmcafe.fixture.Fixture; -import com.project.yozmcafe.service.auth.JwtTokenProvider; -import io.restassured.response.Response; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.restdocs.payload.ResponseFieldsSnippet; -import org.springframework.restdocs.request.QueryParametersSnippet; - -import java.util.List; -import java.util.Objects; - import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_CAFE; import static io.restassured.RestAssured.given; @@ -29,13 +7,36 @@ import static org.assertj.core.groups.Tuple.tuple; import static org.junit.jupiter.api.Assertions.assertAll; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; +import java.util.List; +import java.util.Objects; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.restdocs.payload.ResponseFieldsSnippet; +import org.springframework.restdocs.request.QueryParametersSnippet; + +import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse; +import com.project.yozmcafe.controller.dto.cafe.CafeResponse; +import com.project.yozmcafe.controller.dto.cafe.CafeSearchResponse; +import com.project.yozmcafe.domain.cafe.Cafe; +import com.project.yozmcafe.domain.cafe.CafeRepository; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.domain.menu.MenuRepository; +import com.project.yozmcafe.fixture.Fixture; + +import io.restassured.response.Response; + class CafeControllerTest extends BaseControllerTest { private static final String MEMBER_ID = "memberId"; @@ -47,8 +48,6 @@ class CafeControllerTest extends BaseControllerTest { private CafeRepository cafeRepository; @Autowired private MenuRepository menuRepository; - @MockBean - private JwtTokenProvider jwtTokenProvider; private Cafe cafe1, cafe2, cafe3, cafe4, cafe5; @BeforeEach @@ -63,7 +62,8 @@ void setUp() { @DisplayName("카페에 좋아요를 추가하고, 해당 카페를 조회하는 경우 isLike가 true로 매핑되어 응답한다.") void updateLikesAdd() { //given - given(jwtTokenProvider.getMemberId(anyString())).willReturn(MEMBER_ID); + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); saveMemberAndUnViewedCafes(); final Response likeResponse = given() @@ -99,7 +99,8 @@ private CafeResponse getCafeResponse(final List cafeResponses, lon @DisplayName("카페에 좋아요를 취소하고, 해당 카페를 조회하는 경우 isLike가 false로 매핑되어 응답한다.") void updateLikes() { //given - given(jwtTokenProvider.getMemberId(anyString())).willReturn(MEMBER_ID); + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); saveMemberAndUnViewedCafesAndLikedCafes(); //when @@ -211,7 +212,8 @@ void findByIdWhenNotExist() { @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보내면 아직 보지 않은 랜덤한, 서로 다른 카페정보를 5개씩 응답한다.") void getCafesWithMember() { //given - given(jwtTokenProvider.getMemberId(anyString())).willReturn(MEMBER_ID); + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); final Member member = saveMemberAndUnViewedCafes(); cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 1)); @@ -242,7 +244,8 @@ void getCafesWithMember() { @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보낼 때, 아직보지 않은 카페가 5개 미만이면 남은 수만큼의 서로 다른 카페를 응답한다.") void getCafesWithMemberWhenCafeLessThan() { //given - given(jwtTokenProvider.getMemberId(anyString())).willReturn(MEMBER_ID); + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); saveMemberAndUnViewedCafes(); //when @@ -278,7 +281,8 @@ void getCafesOrderByLikeCount() { //when final Response response = given(spec).log().all() - .filter(document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회", getPageRequestParam(), getCafeRankResponseFields())) + .filter(document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회", getPageRequestParam(), + getCafeRankResponseFields())) .when() .get("/cafes/ranks?page=1"); diff --git a/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java index 64db3fcd..3a2ac284 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java @@ -1,43 +1,42 @@ package com.project.yozmcafe.controller; -import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse; -import com.project.yozmcafe.domain.cafe.Cafe; -import com.project.yozmcafe.domain.cafe.CafeRepository; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.fixture.Fixture; -import com.project.yozmcafe.service.auth.JwtTokenProvider; -import io.restassured.response.Response; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpStatus; -import org.springframework.restdocs.payload.ResponseFieldsSnippet; - -import java.util.List; - import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; import static org.junit.jupiter.api.Assertions.assertAll; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.restdocs.payload.ResponseFieldsSnippet; + +import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse; +import com.project.yozmcafe.domain.cafe.Cafe; +import com.project.yozmcafe.domain.cafe.CafeRepository; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.fixture.Fixture; + +import io.restassured.response.Response; + class LikedCafeControllerTest extends BaseControllerTest { @Autowired private MemberRepository memberRepository; @Autowired private CafeRepository cafeRepository; - @MockBean - private JwtTokenProvider jwtTokenProvider; @Test @DisplayName("사용자가 좋아요 한 카페들의 대표 이미지들을 조회한다.") @@ -90,12 +89,14 @@ void updateLikes() { final Member member = memberRepository.save( new Member("123", "오션", "오션사진")); final Cafe cafe = cafeRepository.save(Fixture.getCafe(1L, "카페1", "주소1", 10)); - given(jwtTokenProvider.getMemberId(anyString())).willReturn(member.getId()); + doReturn(member.getId()).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); //when final Response response = given(spec).log().all() .filter(document("likedCafe/좋아요", - queryParameters(parameterWithName("isLiked").description("true 일 경우 좋아요 추가, false 일 경우 좋아요 취소")), + queryParameters( + parameterWithName("isLiked").description("true 일 경우 좋아요 추가, false 일 경우 좋아요 취소")), pathParameters(parameterWithName("cafeId").description("카페 ID")))) .auth().oauth2("accessToken") .post("/cafes/{cafeId}/likes?isLiked=true", cafe.getId()); diff --git a/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java index 381bef7c..b6366b3d 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java @@ -19,7 +19,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; import com.fasterxml.jackson.databind.ObjectMapper; import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; @@ -27,7 +26,6 @@ import com.project.yozmcafe.controller.dto.cafe.CafeLocationResponse; import com.project.yozmcafe.controller.dto.cafe.CafeRequest; import com.project.yozmcafe.controller.dto.cafe.DetailRequest; -import com.project.yozmcafe.domain.S3Client; import com.project.yozmcafe.domain.cafe.CafeRepository; import com.project.yozmcafe.domain.cafe.available.Days; @@ -37,8 +35,6 @@ class LocationControllerTest extends BaseControllerTest { @Autowired private ObjectMapper mapper; - @SpyBean - private S3Client s3Client; @Autowired CafeRepository cafeRepository; diff --git a/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java b/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java index 3f83924f..491f3b5a 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java @@ -1,34 +1,21 @@ package com.project.yozmcafe.controller; -import com.project.yozmcafe.BaseTest; -import com.project.yozmcafe.util.AcceptanceContext; -import io.restassured.RestAssured; -import org.junit.jupiter.api.BeforeEach; +import static com.project.yozmcafe.exception.ErrorCode.TOKEN_IS_EXPIRED; +import static com.project.yozmcafe.exception.ErrorCode.TOKEN_NOT_EXIST; +import static org.hamcrest.Matchers.is; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; -import static com.project.yozmcafe.exception.ErrorCode.TOKEN_IS_EXPIRED; -import static com.project.yozmcafe.exception.ErrorCode.TOKEN_NOT_EXIST; -import static org.hamcrest.Matchers.is; +import com.project.yozmcafe.util.AcceptanceContext; -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -class LoginArgumentResolverTest extends BaseTest { +class LoginArgumentResolverTest extends BaseControllerTest { - @LocalServerPort - private int port; @Autowired private AcceptanceContext context; - @BeforeEach - void setUp() { - RestAssured.port = port; - } - @Test @DisplayName("만료된 토큰으로 요청을 보내면, 401을 응답한다.") void expiredToken() { From 3a6f72a92dd9c7f27f9eccb96077c0a6d8fa9845 Mon Sep 17 00:00:00 2001 From: dev_kong Date: Wed, 4 Oct 2023 23:43:28 +0900 Subject: [PATCH 02/10] =?UTF-8?q?refactor:=20service=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=ED=9A=9F=EC=88=98=203=20->=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AuthControllerTest.java | 10 ++++++ .../controller/BaseControllerTest.java | 11 ++---- .../yozmcafe/service/BaseServiceTest.java | 15 ++++++++ .../service/CafeAdminServiceTest.java | 3 +- .../yozmcafe/service/CafeServiceTest.java | 30 ++++++++-------- .../yozmcafe/service/ImageServiceTest.java | 12 +++---- .../service/LikedCafeServiceTest.java | 36 ++++++++++--------- .../yozmcafe/service/LocationServiceTest.java | 3 +- .../yozmcafe/service/MemberServiceTest.java | 18 +++++----- .../yozmcafe/service/MenuServiceTest.java | 33 +++++++++-------- .../service/UnViewedCafeServiceTest.java | 22 ++++++------ .../service/auth/AuthServiceTest.java | 29 +++++++-------- .../service/auth/OAuthProviderTest.java | 15 ++++---- 13 files changed, 127 insertions(+), 110 deletions(-) create mode 100644 server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java index ef5ca3bd..4735e368 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java @@ -23,12 +23,16 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpStatus; import com.project.yozmcafe.controller.auth.OAuthProvider; import com.project.yozmcafe.domain.member.Member; import com.project.yozmcafe.domain.member.MemberInfo; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.service.auth.GoogleOAuthClient; import com.project.yozmcafe.service.auth.JwtTokenProvider; +import com.project.yozmcafe.service.auth.KakaoOAuthClient; import io.restassured.http.Cookie; import io.restassured.matcher.DetailedCookieMatcher; @@ -37,6 +41,12 @@ class AuthControllerTest extends BaseControllerTest { + @SpyBean + protected GoogleOAuthClient googleOAuthClient; + @SpyBean + protected KakaoOAuthClient kakaoOAuthClient; + @SpyBean + protected MemberRepository memberRepository; @Autowired JwtTokenProvider jwtTokenProvider; diff --git a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java index 9f229d57..6b54350f 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java @@ -13,10 +13,7 @@ import com.project.yozmcafe.BaseTest; import com.project.yozmcafe.domain.S3Client; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.service.auth.GoogleOAuthClient; import com.project.yozmcafe.service.auth.JwtTokenProvider; -import com.project.yozmcafe.service.auth.KakaoOAuthClient; import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; @@ -28,17 +25,13 @@ public abstract class BaseControllerTest extends BaseTest { @LocalServerPort private int port; - @SpyBean - protected GoogleOAuthClient googleOAuthClient; - @SpyBean - protected KakaoOAuthClient kakaoOAuthClient; - @SpyBean - protected MemberRepository memberRepository; + @SpyBean protected S3Client s3Client; @SpyBean protected JwtTokenProvider jwtTokenProvider; + protected RequestSpecification spec; @BeforeEach diff --git a/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java new file mode 100644 index 00000000..759e9556 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java @@ -0,0 +1,15 @@ +package com.project.yozmcafe.service; + + +import org.springframework.boot.test.mock.mockito.SpyBean; + +import com.project.yozmcafe.BaseTest; +import com.project.yozmcafe.domain.S3Client; +import com.project.yozmcafe.service.auth.GoogleOAuthClient; + +public abstract class BaseServiceTest extends BaseTest { + @SpyBean + protected GoogleOAuthClient googleOAuthClient; + @SpyBean + protected S3Client s3Client; +} diff --git a/server/src/test/java/com/project/yozmcafe/service/CafeAdminServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/CafeAdminServiceTest.java index 7d0084d8..29f7a023 100644 --- a/server/src/test/java/com/project/yozmcafe/service/CafeAdminServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/CafeAdminServiceTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import com.project.yozmcafe.BaseTest; import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; import com.project.yozmcafe.controller.dto.cafe.CafeCoordinateRequest; import com.project.yozmcafe.controller.dto.cafe.CafeRequest; @@ -29,7 +28,7 @@ import com.project.yozmcafe.domain.cafe.coordinate.CafeCoordinateRepository; import com.project.yozmcafe.exception.BadRequestException; -class CafeAdminServiceTest extends BaseTest { +class CafeAdminServiceTest extends BaseServiceTest { @Autowired private CafeAdminService cafeAdminService; diff --git a/server/src/test/java/com/project/yozmcafe/service/CafeServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/CafeServiceTest.java index e46d455e..cf31d5bd 100644 --- a/server/src/test/java/com/project/yozmcafe/service/CafeServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/CafeServiceTest.java @@ -1,6 +1,19 @@ package com.project.yozmcafe.service; -import com.project.yozmcafe.BaseTest; +import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_CAFE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; + import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse; import com.project.yozmcafe.controller.dto.cafe.CafeResponse; import com.project.yozmcafe.controller.dto.cafe.CafeSearchRequest; @@ -12,21 +25,8 @@ import com.project.yozmcafe.domain.menu.MenuRepository; import com.project.yozmcafe.exception.BadRequestException; import com.project.yozmcafe.fixture.Fixture; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; - -import java.util.Arrays; -import java.util.List; - -import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_CAFE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.AssertionsForClassTypes.tuple; -import static org.junit.jupiter.api.Assertions.assertAll; -class CafeServiceTest extends BaseTest { +class CafeServiceTest extends BaseServiceTest { @Autowired private CafeService cafeService; diff --git a/server/src/test/java/com/project/yozmcafe/service/ImageServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/ImageServiceTest.java index d4ef090e..5707a196 100644 --- a/server/src/test/java/com/project/yozmcafe/service/ImageServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/ImageServiceTest.java @@ -7,6 +7,7 @@ import static org.mockito.BDDMockito.anyString; import static org.mockito.BDDMockito.times; import static org.mockito.BDDMockito.verify; +import static org.mockito.Mockito.doNothing; import java.io.File; import java.io.FileInputStream; @@ -16,26 +17,21 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; -import com.project.yozmcafe.BaseTest; -import com.project.yozmcafe.domain.S3Client; import com.project.yozmcafe.domain.resizedimage.Size; -class ImageServiceTest extends BaseTest { +class ImageServiceTest extends BaseServiceTest { @Autowired private ImageService imageService; - @MockBean - private S3Client s3Client; - @Test @DisplayName("모든 사이즈로 리사이즈 이후 업로드 한다") void resizeAndUpload1() { //given + doNothing().when(s3Client).upload(any(MultipartFile.class)); final MockMultipartFile image = makeMultipartFile(); final List images = List.of(image, image, image); @@ -54,6 +50,7 @@ void resizeAndUpload1() { @DisplayName("모바일 사이즈로 리사이즈 이후 업로드한다") void resizeAndUpload2() { //given + doNothing().when(s3Client).upload(any(MultipartFile.class)); final MockMultipartFile file = makeMultipartFile(); //when @@ -67,6 +64,7 @@ void resizeAndUpload2() { @DisplayName("파일 전체 삭제하면 모든 사이즈의 파일을 삭제한다") void deleteAll() { //when + doNothing().when(s3Client).delete(anyString()); imageService.deleteAll(List.of("이미지")); //then diff --git a/server/src/test/java/com/project/yozmcafe/service/LikedCafeServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/LikedCafeServiceTest.java index 04d644f1..546a3a49 100644 --- a/server/src/test/java/com/project/yozmcafe/service/LikedCafeServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/LikedCafeServiceTest.java @@ -1,6 +1,17 @@ package com.project.yozmcafe.service; -import com.project.yozmcafe.BaseTest; +import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_MEMBER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; + import com.project.yozmcafe.controller.dto.cafe.CafeThumbnailResponse; import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse; import com.project.yozmcafe.domain.cafe.Cafe; @@ -9,20 +20,10 @@ import com.project.yozmcafe.domain.member.MemberRepository; import com.project.yozmcafe.exception.BadRequestException; import com.project.yozmcafe.fixture.Fixture; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; - -import java.util.List; -import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_MEMBER; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; +import jakarta.transaction.Transactional; -class LikedCafeServiceTest extends BaseTest { +class LikedCafeServiceTest extends BaseServiceTest { @Autowired private LikedCafeService likedCafeService; @@ -42,7 +43,8 @@ void findLikedCafesById() { memberRepository.save(member); //when - final List likedCafes = likedCafeService.findLikedCafeThumbnailsByMemberId(member.getId(), pageRequest); + final List likedCafes = likedCafeService.findLikedCafeThumbnailsByMemberId( + member.getId(), pageRequest); //then assertThat(likedCafes.get(0).cafeId()).isEqualTo(savedCafe.getId()); @@ -56,7 +58,8 @@ void findLikedCafesById_fail() { //when //then - assertThatThrownBy(() -> likedCafeService.findLikedCafeThumbnailsByMemberId("findLikedCafesById_fail", pageRequest)) + assertThatThrownBy( + () -> likedCafeService.findLikedCafeThumbnailsByMemberId("findLikedCafesById_fail", pageRequest)) .isInstanceOf(BadRequestException.class) .hasMessage(NOT_EXISTED_MEMBER.getMessage()); } @@ -76,7 +79,8 @@ void findLikedCafesById_empty() { final PageRequest pageRequest = PageRequest.of(1, 2); //when - final List likedCafesById = likedCafeService.findLikedCafeThumbnailsByMemberId(member.getId(), pageRequest); + final List likedCafesById = likedCafeService.findLikedCafeThumbnailsByMemberId( + member.getId(), pageRequest); //then assertThat(likedCafesById).isEmpty(); diff --git a/server/src/test/java/com/project/yozmcafe/service/LocationServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/LocationServiceTest.java index a5c6cd8f..98575cc4 100644 --- a/server/src/test/java/com/project/yozmcafe/service/LocationServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/LocationServiceTest.java @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import com.project.yozmcafe.BaseTest; import com.project.yozmcafe.controller.dto.cafe.CafeLocationRequest; import com.project.yozmcafe.controller.dto.cafe.CafeLocationResponse; import com.project.yozmcafe.domain.cafe.Cafe; @@ -19,7 +18,7 @@ import com.project.yozmcafe.domain.cafe.coordinate.CafeCoordinateRepository; import com.project.yozmcafe.fixture.Fixture; -class LocationServiceTest extends BaseTest { +class LocationServiceTest extends BaseServiceTest { @Autowired private LocationService locationService; diff --git a/server/src/test/java/com/project/yozmcafe/service/MemberServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/MemberServiceTest.java index 43aaeb9e..bd67ac0a 100644 --- a/server/src/test/java/com/project/yozmcafe/service/MemberServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/MemberServiceTest.java @@ -1,21 +1,21 @@ package com.project.yozmcafe.service; -import com.project.yozmcafe.BaseTest; -import com.project.yozmcafe.controller.dto.MemberResponse; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.exception.BadRequestException; +import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_MEMBER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; -import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_MEMBER; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.project.yozmcafe.controller.dto.MemberResponse; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.exception.BadRequestException; @Transactional -class MemberServiceTest extends BaseTest { +class MemberServiceTest extends BaseServiceTest { @Autowired private MemberService memberService; diff --git a/server/src/test/java/com/project/yozmcafe/service/MenuServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/MenuServiceTest.java index 5f03839b..5a8b0737 100644 --- a/server/src/test/java/com/project/yozmcafe/service/MenuServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/MenuServiceTest.java @@ -1,6 +1,13 @@ package com.project.yozmcafe.service; -import com.project.yozmcafe.BaseTest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + import com.project.yozmcafe.controller.dto.menu.MenuBoardResponse; import com.project.yozmcafe.controller.dto.menu.MenuItemResponse; import com.project.yozmcafe.controller.dto.menu.MenuResponse; @@ -11,16 +18,9 @@ import com.project.yozmcafe.domain.menu.MenuBoardRepository; import com.project.yozmcafe.domain.menu.MenuRepository; import com.project.yozmcafe.fixture.Fixture; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; @Transactional -class MenuServiceTest extends BaseTest { +class MenuServiceTest extends BaseServiceTest { @Autowired private MenuService menuService; @@ -36,8 +36,9 @@ class MenuServiceTest extends BaseTest { void getMenus() { //given final Cafe savedCafe = cafeRepository.save(Fixture.getCafe("오션카페", "서울카페", 0)); - final Menu savedMenu = menuRepository.save(new Menu(savedCafe, 1, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", - true)); + final Menu savedMenu = menuRepository.save( + new Menu(savedCafe, 1, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", + true)); final MenuBoard savedMenuBoard = menuBoardRepository.save(new MenuBoard(savedCafe, 1, "메뉴판 이미지")); //when @@ -56,10 +57,12 @@ void getMenus() { void getMenus_sort() { //given final Cafe savedCafe = cafeRepository.save(Fixture.getCafe("오션카페", "서울카페", 0)); - final Menu savedMenu = menuRepository.save(new Menu(savedCafe, 1, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", - false)); - final Menu savedMenu2 = menuRepository.save(new Menu(savedCafe, 2, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", - true)); + final Menu savedMenu = menuRepository.save( + new Menu(savedCafe, 1, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", + false)); + final Menu savedMenu2 = menuRepository.save( + new Menu(savedCafe, 2, "따뜻한 아이스 아메리카노", "아메리카노.img", "고소한 아메리카노", "5000", + true)); final MenuBoard savedMenuBoard = menuBoardRepository.save(new MenuBoard(savedCafe, 1, "메뉴판 이미지")); final MenuBoard savedMenuBoard2 = menuBoardRepository.save(new MenuBoard(savedCafe, 2, "메뉴판 이미지")); diff --git a/server/src/test/java/com/project/yozmcafe/service/UnViewedCafeServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/UnViewedCafeServiceTest.java index a9c037b7..1cb08cd4 100644 --- a/server/src/test/java/com/project/yozmcafe/service/UnViewedCafeServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/UnViewedCafeServiceTest.java @@ -1,23 +1,23 @@ package com.project.yozmcafe.service; -import com.project.yozmcafe.BaseTest; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + import com.project.yozmcafe.domain.RandomCafeShuffleStrategy; import com.project.yozmcafe.domain.cafe.Cafe; import com.project.yozmcafe.domain.cafe.CafeRepository; import com.project.yozmcafe.domain.member.Member; import com.project.yozmcafe.domain.member.MemberRepository; import com.project.yozmcafe.fixture.Fixture; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -class UnViewedCafeServiceTest extends BaseTest { +class UnViewedCafeServiceTest extends BaseServiceTest { private UnViewedCafeService unViewedCafeService; diff --git a/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java index b736c0b4..fea32167 100644 --- a/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java @@ -1,6 +1,16 @@ package com.project.yozmcafe.service.auth; -import com.project.yozmcafe.BaseTest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.anyString; +import static org.mockito.Mockito.doReturn; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + import com.project.yozmcafe.controller.auth.OAuthProvider; import com.project.yozmcafe.controller.dto.AuthorizationUrlDto; import com.project.yozmcafe.domain.cafe.Cafe; @@ -10,23 +20,10 @@ import com.project.yozmcafe.domain.member.MemberInfo; import com.project.yozmcafe.domain.member.MemberRepository; import com.project.yozmcafe.fixture.Fixture; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.anyString; -import static org.mockito.Mockito.doReturn; +import com.project.yozmcafe.service.BaseServiceTest; @Transactional -class AuthServiceTest extends BaseTest { - - @SpyBean - private GoogleOAuthClient googleOAuthClient; +class AuthServiceTest extends BaseServiceTest { @Autowired private MemberRepository memberRepository; diff --git a/server/src/test/java/com/project/yozmcafe/service/auth/OAuthProviderTest.java b/server/src/test/java/com/project/yozmcafe/service/auth/OAuthProviderTest.java index df773503..69ee30c7 100644 --- a/server/src/test/java/com/project/yozmcafe/service/auth/OAuthProviderTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/auth/OAuthProviderTest.java @@ -1,19 +1,18 @@ package com.project.yozmcafe.service.auth; -import com.project.yozmcafe.BaseTest; -import com.project.yozmcafe.controller.auth.OAuthProvider; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import org.springframework.transaction.annotation.Transactional; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import com.project.yozmcafe.controller.auth.OAuthProvider; +import com.project.yozmcafe.service.BaseServiceTest; -@Transactional -class OAuthProviderTest extends BaseTest { +class OAuthProviderTest extends BaseServiceTest { @Test @DisplayName("OAuthProvider와 OAuthClient가 매핑되지 않으면 실패") From a895e83b9c45582af184a9080a95bce50bf5553a Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 15:12:57 +0900 Subject: [PATCH 03/10] =?UTF-8?q?test:=20LoginArgumentResolverTest=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20&=20AcceptanceContext.java=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-test.yaml | 6 +- .../controller/BaseControllerTest.java | 21 +++ .../controller/LoginArgumentResolverTest.java | 58 +++++--- .../yozmcafe/util/AcceptanceContext.java | 134 ------------------ 4 files changed, 61 insertions(+), 158 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/util/AcceptanceContext.java diff --git a/server/src/main/resources/application-test.yaml b/server/src/main/resources/application-test.yaml index 0bfd905e..71234fea 100644 --- a/server/src/main/resources/application-test.yaml +++ b/server/src/main/resources/application-test.yaml @@ -1,3 +1,5 @@ +log: &log-option false + spring: auth: key: testtesttesttesttesttesttesttesttesttesttesttesttesttesttest @@ -33,8 +35,8 @@ spring: properties: hibernate: default_batch_fetch_size: 1000 - format_sql: true - show-sql: true + format_sql: *log-option + show-sql: *log-option s3: bucket: 2023-team-project/2023-yozm-cafe/test/images diff --git a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java index 6b54350f..dfe7fc27 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/BaseControllerTest.java @@ -1,9 +1,11 @@ package com.project.yozmcafe.controller; +import static io.restassured.RestAssured.given; import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.mock.mockito.SpyBean; @@ -17,6 +19,7 @@ import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; +import io.restassured.filter.Filter; import io.restassured.specification.RequestSpecification; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @@ -31,6 +34,8 @@ public abstract class BaseControllerTest extends BaseTest { @SpyBean protected JwtTokenProvider jwtTokenProvider; + @Value("${log}") + private boolean showLog; protected RequestSpecification spec; @@ -40,4 +45,20 @@ void setUp(RestDocumentationContextProvider restDocumentation) { this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(restDocumentation)) .build(); } + + protected RequestSpecification customGiven() { + final RequestSpecification customGiven = given(); + if (showLog) { + return customGiven.log().all(); + } + return customGiven; + } + + protected RequestSpecification customGivenWithDocs(Filter document) { + final RequestSpecification customGiven = given(spec).filter(document); + if (showLog) { + return customGiven.log().all(); + } + return customGiven; + } } diff --git a/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java b/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java index 491f3b5a..f4d31094 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/LoginArgumentResolverTest.java @@ -2,60 +2,74 @@ import static com.project.yozmcafe.exception.ErrorCode.TOKEN_IS_EXPIRED; import static com.project.yozmcafe.exception.ErrorCode.TOKEN_NOT_EXIST; -import static org.hamcrest.Matchers.is; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import com.project.yozmcafe.util.AcceptanceContext; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; class LoginArgumentResolverTest extends BaseControllerTest { - @Autowired - private AcceptanceContext context; - @Test @DisplayName("만료된 토큰으로 요청을 보내면, 401을 응답한다.") void expiredToken() { //given - context.accessToken = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2OTA4NjQ5NzQsImV4cCI6MTY5MDg2NTMzNCwic3ViIjoiMjkzOTU1Mzk2NyJ9.m8s0N30wn8g9eccIXRneOdhCsB_EZbR5etceyw2RaO4"; + String expiredToken = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2OTA4NjQ5NzQsImV4cCI6MTY5MDg2NTMzNCwic3ViIjoiMjkzOTU1Mzk2NyJ9.m8s0N30wn8g9eccIXRneOdhCsB_EZbR5etceyw2RaO4"; //when - context.invokeHttpGetWithToken("/cafes?page=1"); + final ExtractableResponse response = customGiven() + .header("Authorization", expiredToken) + .when() + .get("/cafes") + .then() + .extract(); //then - context.response.then() - .statusCode(HttpStatus.UNAUTHORIZED.value()) - .body("code", is(TOKEN_IS_EXPIRED.getCode())) - .body("message", is(TOKEN_IS_EXPIRED.getMessage())); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(UNAUTHORIZED.value()); + assertThat(response.jsonPath().getString("code")).isEqualTo(TOKEN_IS_EXPIRED.getCode()); + assertThat(response.jsonPath().getString("message")).isEqualTo(TOKEN_IS_EXPIRED.getMessage()); + }); } @Test @DisplayName("잘못된 토큰으로 요청을 보내면 500을 응답한다.") void invalidToken() { //given - context.accessToken = "ahahah"; + String expiredToken = "invalidToken"; //when - context.invokeHttpGetWithToken("/cafes?page=1"); + final ExtractableResponse response = customGiven() + .header("Authorization", expiredToken) + .when() + .get("/cafes") + .then() + .extract(); //then - context.response.then() - .statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); + assertThat(response.statusCode()).isEqualTo(INTERNAL_SERVER_ERROR.value()); } @Test @DisplayName("토큰이 존재하지 않으면 401을 응답한다.") void notExistToken() { //when - context.invokeHttpGet("/cafes?page=1"); + final ExtractableResponse response = customGiven() + .when() + .get("/cafes") + .then() + .extract(); //then - context.response.then() - .statusCode(HttpStatus.UNAUTHORIZED.value()) - .body("code", is(TOKEN_NOT_EXIST.getCode())) - .body("message", is(TOKEN_NOT_EXIST.getMessage())); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(UNAUTHORIZED.value()); + assertThat(response.jsonPath().getString("code")).isEqualTo(TOKEN_NOT_EXIST.getCode()); + assertThat(response.jsonPath().getString("message")).isEqualTo(TOKEN_NOT_EXIST.getMessage()); + }); } } diff --git a/server/src/test/java/com/project/yozmcafe/util/AcceptanceContext.java b/server/src/test/java/com/project/yozmcafe/util/AcceptanceContext.java deleted file mode 100644 index b57bad17..00000000 --- a/server/src/test/java/com/project/yozmcafe/util/AcceptanceContext.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.project.yozmcafe.util; - -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import io.restassured.http.Cookie; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -@Component -public class AcceptanceContext { - - public RequestSpecification request; - public Response response; - public String accessToken; - public Map storage; - - public AcceptanceContext() { - reset(); - } - - private void reset() { - request = null; - response = null; - accessToken = ""; - storage = new HashMap<>(); - } - - public void invokeHttpGet(String path, Object... pathParams) { - request = RestAssured.given().log().all(); - response = request.when().get(path, pathParams); - response.then().log().all(); - } - - public void invokeHttpPost(String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON); - response = request.post(path); - response.then().log().all(); - } - - public void invokeHttpPut(final String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON); - response = request.put(path); - response.then().log().all(); - } - - public void invokeHttpDelete(final String path, Object... pathParams) { - request = RestAssured.given().log().all(); - response = request.when().delete(path, pathParams); - response.then().log().all(); - } - - public void invokeHttpGetWithToken(String path, Object... pathParams) { - request = RestAssured.given().log().all() - .auth().oauth2(accessToken); - response = request.when().get(path, pathParams); - response.then().log().all(); - } - - public void invokeHttpGetWithTokenAndCookies(String path, Map cookies, Object... pathParams) { - request = RestAssured.given().log().all() - .cookies(cookies) - .auth().oauth2(accessToken); - response = request.when().get(path, pathParams); - response.then().log().all(); - } - - public void invokeHttpPutWithToken(String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON) - .auth().oauth2(accessToken); - response = request.put(path); - response.then().log().all(); - } - - public void invokeHttpPatchWithToken(String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON) - .auth().oauth2(accessToken); - response = request.patch(path); - response.then().log().all(); - } - - public void invokeHttpPostWithToken(String path) { - request = RestAssured - .given().log().all() - .auth().oauth2(accessToken); - response = request.post(path); - response.then().log().all(); - } - - public void invokeHttpPostWithToken(String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON) - .auth().oauth2(accessToken); - response = request.post(path); - response.then().log().all(); - } - - public void invokeHttpDeleteWithToken(String path) { - request = RestAssured - .given().log().all() - .auth().oauth2(accessToken); - response = request.delete(path); - response.then().log().all(); - } - - public void invokeHttpDeleteWithToken(String path, Object data) { - request = RestAssured - .given().log().all() - .body(data).contentType(ContentType.JSON) - .auth().oauth2(accessToken); - response = request.delete(path); - response.then().log().all(); - } - - public void invokeHttpDeleteWithCookie(String path, Cookie cookie) { - request = RestAssured - .given().log().all() - .cookie(cookie); - response = request.delete(path); - response.then().log().all(); - } -} From 52cd64d3d906fea255b66d5cb711386e17b4635e Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 16:14:18 +0900 Subject: [PATCH 04/10] =?UTF-8?q?test:=20AuthControllerTest=20customGiven?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AuthControllerTest.java | 203 ------------------ .../controller/auth/AuthControllerTest.java | 167 ++++++++++++++ .../controller/auth/AuthDocuments.java | 44 ++++ 3 files changed, 211 insertions(+), 203 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/auth/AuthControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/auth/AuthDocuments.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java deleted file mode 100644 index 4735e368..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/AuthControllerTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.project.yozmcafe.controller; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doReturn; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; -import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; -import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; - -import java.util.Optional; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.http.HttpStatus; - -import com.project.yozmcafe.controller.auth.OAuthProvider; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberInfo; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.service.auth.GoogleOAuthClient; -import com.project.yozmcafe.service.auth.JwtTokenProvider; -import com.project.yozmcafe.service.auth.KakaoOAuthClient; - -import io.restassured.http.Cookie; -import io.restassured.matcher.DetailedCookieMatcher; -import io.restassured.matcher.RestAssuredMatchers; -import io.restassured.response.Response; - -class AuthControllerTest extends BaseControllerTest { - - @SpyBean - protected GoogleOAuthClient googleOAuthClient; - @SpyBean - protected KakaoOAuthClient kakaoOAuthClient; - @SpyBean - protected MemberRepository memberRepository; - @Autowired - JwtTokenProvider jwtTokenProvider; - - @Test - @DisplayName("Provider Google OAuth login을 한다.") - void loginWithGoogle() { - //given - doReturn(new MemberInfo("openId", "오션", "바다.img")) - .when(googleOAuthClient).getUserInfo(anyString()); - - given(memberRepository.findById(anyString())) - .willReturn(Optional.of(new Member("openId", "오션", "바다.img"))); - - //when - final Response response = given(spec) - .log().all() - .filter(document("OAuth/OAuth 로그인", - queryParameters(parameterWithName("code").description("Authorization Code")), - pathParameters(parameterWithName("providerName").description("OAuth Provider")), - responseFields(fieldWithPath("token").description("Access Token")), - responseCookies(cookieWithName("refreshToken").description("Refresh Token")))) - .when() - .post("/auth/{providerName}?code=googleCode", "google"); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getString("token")).isNotNull(), - () -> assertThat(response.cookie("refreshToken")).isNotNull() - ); - } - - @Test - @DisplayName("Provider Kakao OAuth login을 한다.") - void loginWithKakao() { - //given - doReturn(new MemberInfo("openId", "오션", "바다.img")) - .when(kakaoOAuthClient).getUserInfo(anyString()); - - given(memberRepository.findById(anyString())) - .willReturn(Optional.of(new Member("openId", "오션", "바다.img"))); - - //when - final Response response = given() - .log().all() - .queryParam("code", "googleCode") - .when() - .post("/auth/{providerName}", "kakao"); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getString("token")).isNotNull(), - () -> assertThat(response.cookie("refreshToken")).isNotNull() - ); - } - - @Test - @DisplayName("토큰을 갱신한다.") - void refreshToken() { - //given - final String accessToken = jwtTokenProvider.createAccessFrom("1L"); - final String refreshToken = jwtTokenProvider.createRefresh(); - - //when - final Response response = given(spec).log().all() - .filter(document("OAuth/토큰 갱신", - requestHeaders(headerWithName("Authorization").description("Access Token")), - requestCookies(cookieWithName("refreshToken").description("Refresh Token")), - responseFields(fieldWithPath("token").description("Access Token")), - responseCookies(cookieWithName("refreshToken").description("Refresh Token")))) - .header("Authorization", accessToken) - .cookie("refreshToken", refreshToken) - .when() - .log().all() - .get("/auth"); - - //then - assertAll( - () -> assertThat(response.jsonPath().getString("token")).isNotNull(), - () -> assertThat(response.cookie("refreshToken")).isNotNull() - ); - } - - @Test - @DisplayName("Provider 인증 주소를 반환한다.") - void authorizationUrls() { - //when - final Response response = given(spec).log().all() - .filter(document("OAuth/OAuth Provider Url", - responseFields(fieldWithPath("[].provider").description("OAuth Provider 이름"), - fieldWithPath("[].authorizationUrl").description("Provider 인증 Url")))) - .when() - .log().all() - .get("/auth/urls"); - - //then - for (OAuthProvider provider : OAuthProvider.values()) { - String providerPath = "[" + provider.ordinal() + "]" + ".provider"; - String urlPath = "[" + provider.ordinal() + "]" + ".authorizationUrl"; - - assertThat(response.getBody().jsonPath().getString(providerPath)).isEqualTo(provider.getProviderName()); - assertThat(response.getBody().jsonPath().getString(urlPath)) - .contains("response_type", "redirect_uri", "client_id", "scope"); - } - } - - @Test - @DisplayName("로그아웃을 한다") - void logout() { - //given - final Cookie cookie = new Cookie.Builder("refreshToken", "리프레시").build(); - final DetailedCookieMatcher expectedDetail = RestAssuredMatchers.detailedCookie() - .value("") - .maxAge(0); - - //when - final Response response = given(spec).log().all() - .filter(document("OAuth/OAuth 로그아웃", - requestCookies(cookieWithName("refreshToken").description("Refresh Token")) - )) - .cookie(cookie) - .delete("/auth"); - - //then - response.then().log().all() - .statusCode(HttpStatus.OK.value()) - .cookie("refreshToken", expectedDetail); - } - - @Test - @DisplayName("새로운 유저가 로그인한다.") - void register() { - //given - doReturn(new MemberInfo("openId", "오션", "바다.img")) - .when(googleOAuthClient).getUserInfo(anyString()); - - given(memberRepository.findById(anyString())) - .willReturn(Optional.empty()); - - //when - final Response response = given() - .log().all() - .when() - .post("/auth/{providerName}?code=googleCode", "google"); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()), - () -> assertThat(response.jsonPath().getString("token")).isNotNull(), - () -> assertThat(response.cookie("refreshToken")).isNotNull() - ); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/auth/AuthControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/auth/AuthControllerTest.java new file mode 100644 index 00000000..088759c3 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/auth/AuthControllerTest.java @@ -0,0 +1,167 @@ +package com.project.yozmcafe.controller.auth; + +import static com.project.yozmcafe.controller.auth.AuthDocuments.logoutDocument; +import static com.project.yozmcafe.controller.auth.AuthDocuments.oAuthLoginDocument; +import static com.project.yozmcafe.controller.auth.AuthDocuments.oAuthUrlDocument; +import static com.project.yozmcafe.controller.auth.AuthDocuments.updateTokenDocument; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.springframework.http.HttpStatus.OK; + +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.SpyBean; + +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberInfo; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.service.auth.GoogleOAuthClient; +import com.project.yozmcafe.service.auth.JwtTokenProvider; +import com.project.yozmcafe.service.auth.KakaoOAuthClient; + +import io.restassured.http.Cookie; +import io.restassured.matcher.DetailedCookieMatcher; +import io.restassured.matcher.RestAssuredMatchers; +import io.restassured.response.Response; + +class AuthControllerTest extends BaseControllerTest { + + @SpyBean + protected GoogleOAuthClient googleOAuthClient; + @SpyBean + protected KakaoOAuthClient kakaoOAuthClient; + @SpyBean + protected MemberRepository memberRepository; + @Autowired + JwtTokenProvider jwtTokenProvider; + + @Test + @DisplayName("Provider Google OAuth login을 한다.") + void loginWithGoogle() { + //given + doReturn(new MemberInfo("openId", "오션", "바다.img")) + .when(googleOAuthClient).getUserInfo(anyString()); + doReturn(Optional.of(new Member("openId", "오션", "바다.img"))) + .when(memberRepository).findById(anyString()); + + //when + final Response response = customGivenWithDocs(oAuthLoginDocument()) + .queryParam("code", "googleCode") + .post("/auth/{providerName}?code=googleCode", "google"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(response.jsonPath().getString("token")).isNotNull(); + assertThat(response.cookie("refreshToken")).isNotNull(); + }); + } + + @Test + @DisplayName("Provider Kakao OAuth login을 한다.") + void loginWithKakao() { + //given + doReturn(new MemberInfo("openId", "오션", "바다.img")) + .when(kakaoOAuthClient).getUserInfo(anyString()); + doReturn(Optional.of(new Member("openId", "오션", "바다.img"))) + .when(memberRepository).findById(anyString()); + + //when + final Response response = customGiven() + .queryParam("code", "kakaoCode") + .post("/auth/{providerName}", "kakao"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(response.jsonPath().getString("token")).isNotNull(); + assertThat(response.cookie("refreshToken")).isNotNull(); + }); + } + + @Test + @DisplayName("토큰을 갱신한다.") + void refreshToken() { + //given + final String accessToken = jwtTokenProvider.createAccessFrom("1L"); + final String refreshToken = jwtTokenProvider.createRefresh(); + + //when + final Response response = customGivenWithDocs(updateTokenDocument()) + .header("Authorization", accessToken) + .cookie("refreshToken", refreshToken) + .get("/auth"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.jsonPath().getString("token")).isNotNull(); + assertThat(response.cookie("refreshToken")).isNotNull(); + }); + } + + @Test + @DisplayName("Provider 인증 주소를 반환한다.") + void authorizationUrls() { + //when + final Response response = customGivenWithDocs(oAuthUrlDocument()) + .get("/auth/urls"); + + //then + for (OAuthProvider provider : OAuthProvider.values()) { + String providerPath = "[" + provider.ordinal() + "]" + ".provider"; + String urlPath = "[" + provider.ordinal() + "]" + ".authorizationUrl"; + + assertThat(response.getBody().jsonPath().getString(providerPath)).isEqualTo(provider.getProviderName()); + assertThat(response.getBody().jsonPath().getString(urlPath)) + .contains("response_type", "redirect_uri", "client_id", "scope"); + } + } + + @Test + @DisplayName("로그아웃을 한다") + void logout() { + //given + final Cookie cookie = new Cookie.Builder("refreshToken", "리프레시").build(); + final DetailedCookieMatcher expectedDetail = RestAssuredMatchers.detailedCookie() + .value("") + .maxAge(0); + + //when + final Response response = customGivenWithDocs(logoutDocument()) + .cookie(cookie) + .delete("/auth"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(expectedDetail.matches(response.detailedCookie("refreshToken"))).isTrue(); + }); + } + + @Test + @DisplayName("새로운 유저가 로그인한다.") + void register() { + //given + doReturn(new MemberInfo("openId", "오션", "바다.img")) + .when(googleOAuthClient).getUserInfo(anyString()); + doReturn(Optional.empty()) + .when(memberRepository).findById(anyString()); + + //when + final Response response = customGiven() + .post("/auth/{providerName}?code=googleCode", "google"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(response.jsonPath().getString("token")).isNotNull(); + assertThat(response.cookie("refreshToken")).isNotNull(); + }); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/auth/AuthDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/auth/AuthDocuments.java new file mode 100644 index 00000000..d049cd74 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/auth/AuthDocuments.java @@ -0,0 +1,44 @@ +package com.project.yozmcafe.controller.auth; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class AuthDocuments { + public static RestDocumentationFilter oAuthLoginDocument() { + return document("OAuth/OAuth 로그인", + queryParameters(parameterWithName("code").description("Authorization Code")), + pathParameters(parameterWithName("providerName").description("OAuth Provider")), + responseFields(fieldWithPath("token").description("Access Token")), + responseCookies(cookieWithName("refreshToken").description("Refresh Token"))); + } + + public static RestDocumentationFilter updateTokenDocument() { + return document("OAuth/토큰 갱신", + requestHeaders(headerWithName("Authorization").description("Access Token")), + requestCookies(cookieWithName("refreshToken").description("Refresh Token")), + responseFields(fieldWithPath("token").description("Access Token")), + responseCookies(cookieWithName("refreshToken").description("Refresh Token"))); + } + + public static RestDocumentationFilter oAuthUrlDocument() { + return document("OAuth/OAuth Provider Url", + responseFields(fieldWithPath("[].provider").description("OAuth Provider 이름"), + fieldWithPath("[].authorizationUrl").description("Provider 인증 Url"))); + } + + public static RestDocumentationFilter logoutDocument() { + return document("OAuth/OAuth 로그아웃", + requestCookies(cookieWithName("refreshToken").description("Refresh Token"))); + } +} From 862d459f644b469a92c4e0bd5df11a35ec44fa3e Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 17:22:43 +0900 Subject: [PATCH 05/10] =?UTF-8?q?test:=20AdminController=20&=20CafeControl?= =?UTF-8?q?ler=20CustomGiven=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CafeAdminControllerTest.java | 254 ---------- .../controller/CafeControllerTest.java | 470 ------------------ .../controller/admin/AdminDocuments.java | 81 +++ .../admin/CafeAdminControllerTest.java | 205 ++++++++ .../controller/cafe/CafeControllerTest.java | 357 +++++++++++++ .../controller/cafe/CafeDocuments.java | 115 +++++ 6 files changed, 758 insertions(+), 724 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/admin/AdminDocuments.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/cafe/CafeControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/cafe/CafeDocuments.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java deleted file mode 100644 index 941ab7a0..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/CafeAdminControllerTest.java +++ /dev/null @@ -1,254 +0,0 @@ -package com.project.yozmcafe.controller; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static io.restassured.http.ContentType.MULTIPART; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; -import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestPartBody; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; - -import java.io.File; -import java.time.LocalTime; -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.web.multipart.MultipartFile; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; -import com.project.yozmcafe.controller.dto.cafe.CafeCoordinateRequest; -import com.project.yozmcafe.controller.dto.cafe.CafeRequest; -import com.project.yozmcafe.controller.dto.cafe.CafeUpdateRequest; -import com.project.yozmcafe.controller.dto.cafe.DetailRequest; -import com.project.yozmcafe.domain.cafe.available.Days; - -class CafeAdminControllerTest extends BaseControllerTest { - - @Autowired - private ObjectMapper mapper; - - private File image = new File("src/test/resources/image.png"); - - @Test - @DisplayName("카페 저장하기") - void save() { - //given - doNothing().when(s3Client).upload(any(MultipartFile.class)); - final String cafeRequestJson = makeCafeRequest(); - - //when, then - given(spec).log().all() - .contentType(MULTIPART) - .multiPart("request", cafeRequestJson, "application/json") - .multiPart("images", image, "image/png") - .accept(JSON) - .filter(document("어드민 API/카페 저장하기", - requestPartBody("request"), requestPartBody("images"), - responseHeaders(headerWithName("Location").description("카페 저장 위치")))) - .when() - .post("/admin/cafes") - .then() - .statusCode(is(HttpStatus.CREATED.value())) - .header("Location", notNullValue()); - } - - @Test - @DisplayName("카페 업데이트") - void update() { - //given - doNothing().when(s3Client).upload(any(MultipartFile.class)); - doNothing().when(s3Client).delete(anyString()); - String location = saveCafe(); - String updateRequest = makeCafeUpdateRequest(); - - //when, then - given(spec).log().all() - .contentType(MULTIPART) - .multiPart("request", updateRequest, "application/json") - .multiPart("images", image, "image/png") - .accept(JSON) - .filter(document("어드민 API/카페 업데이트하기", - requestPartBody("request"), requestPartBody("images"), - pathParameters(parameterWithName("cafeId").description("업데이트할 카페 ID")))) - .when() - .put("/admin/cafes/{cafeId}", location) - .then() - .statusCode(is(HttpStatus.NO_CONTENT.value())); - } - - @Test - @DisplayName("카페 삭제") - void delete() { - //given - doNothing().when(s3Client).delete(anyString()); - String location = saveCafe(); - - //when, then - given(spec).log().all() - .contentType(JSON) - .filter(document("어드민 API/카페 삭제하기", - pathParameters(parameterWithName("cafeId").description("삭제할 카페 ID")))) - .when() - .delete("/admin/cafes/{cafeId}", location) - .then() - .statusCode(is(HttpStatus.NO_CONTENT.value())); - } - - @Test - @DisplayName("카페 전체 조회") - void findAll() { - //given - saveCafe(); - saveCafe(); - - //when, then - given(spec).log().all() - .contentType(JSON) - .filter(document("어드민 API/카페 전체 조회하기", - responseFields( - fieldWithPath("[].id").description("카페 ID"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 도로명 주소"), - fieldWithPath("[].isLiked").description("좋아요 누른 여부"), - fieldWithPath("[].likeCount").description("좋아요 숫자"), - fieldWithPath("[].images.[]").description("이미지 URL 배열"), - fieldWithPath("[].detail.mapUrl").description("네이버 지도 URL"), - fieldWithPath("[].detail.description").description("상세 설명"), - fieldWithPath("[].detail.phone").description("전화번호"), - fieldWithPath("[].detail.openingHours.[].day").description("요일"), - fieldWithPath("[].detail.openingHours.[].open").description("영업 시작 시각"), - fieldWithPath("[].detail.openingHours.[].close").description("영업 종료 시각"), - fieldWithPath("[].detail.openingHours.[].opened").description("해당 요일 영업 여부")) - )) - .when() - .get("/admin/cafes") - .then() - .statusCode(is(HttpStatus.OK.value())); - } - - @Test - @DisplayName("카페 단건 조회") - void findById() { - //given - String location = saveCafe(); - - //when, then - given(spec).log().all() - .contentType(JSON) - .filter(document("어드민 API/카페 단건 조회하기", - pathParameters(parameterWithName("cafeId").description("조회할 카페 ID")), - responseFields( - fieldWithPath("id").description("카페 ID"), - fieldWithPath("name").description("카페 이름"), - fieldWithPath("address").description("카페 도로명 주소"), - fieldWithPath("isLiked").description("좋아요 누른 여부"), - fieldWithPath("likeCount").description("좋아요 숫자"), - fieldWithPath("images.[]").description("이미지 URL 배열"), - fieldWithPath("detail.mapUrl").description("네이버 지도 URL"), - fieldWithPath("detail.description").description("상세 설명"), - fieldWithPath("detail.phone").description("전화번호"), - fieldWithPath("detail.openingHours.[].day").description("요일"), - fieldWithPath("detail.openingHours.[].open").description("영업 시작 시각"), - fieldWithPath("detail.openingHours.[].close").description("영업 종료 시각"), - fieldWithPath("detail.openingHours.[].opened").description("해당 요일 영업 여부")) - )) - .when() - .get("/admin/cafes/{cafeId}", location) - .then() - .statusCode(is(HttpStatus.OK.value())); - } - - @Test - @DisplayName("좌표 정보를 저장한다.") - void saveCoordinate() { - //given - final String location = saveCafe(); - - //when, then - given(spec).log().all() - .contentType(JSON) - .filter(document("어드민 API/좌표 정보 저장", - pathParameters(parameterWithName("cafeId").description("죄표를 추가할 카페 ID")), - requestFields( - fieldWithPath("latitude").description("위도"), - fieldWithPath("longitude").description("경도") - ), - responseHeaders(headerWithName("Location").description("카페 저장 위치")) - )) - .when() - .body(new CafeCoordinateRequest(20, 10)) - .post("/admin/cafes/{cafeId}/coordinate", location) - .then() - .statusCode(is(HttpStatus.CREATED.value())) - .header("Location", notNullValue()); - } - - private String saveCafe() { - doNothing().when(s3Client).upload(any(MultipartFile.class)); - final String cafeRequest = makeCafeRequest(); - - final String location = given().log().all() - .contentType(MULTIPART) - .multiPart("request", cafeRequest, "application/json") - .multiPart("images", image, "image/png") - .accept(JSON) - .when() - .post("/admin/cafes") - .then() - .extract().header("Location"); - - String[] split = location.split("/"); - - return split[split.length - 1]; - } - - private String makeCafeRequest() { - try { - return mapper.writeValueAsString(new CafeRequest("연어카페", "광안리", detail())); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private String makeCafeUpdateRequest() { - try { - return mapper.writeValueAsString(new CafeUpdateRequest("참치전문점", "해운대", detail(), 100)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private DetailRequest detail() { - final AvailableTimeRequest time1 = new AvailableTimeRequest(Days.MONDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time2 = new AvailableTimeRequest(Days.TUESDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time3 = new AvailableTimeRequest(Days.WEDNESDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time4 = new AvailableTimeRequest(Days.THURSDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time5 = new AvailableTimeRequest(Days.FRIDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time6 = new AvailableTimeRequest(Days.SATURDAY, LocalTime.now(), LocalTime.now(), - true); - final AvailableTimeRequest time7 = new AvailableTimeRequest(Days.SUNDAY, LocalTime.now(), LocalTime.now(), - true); - - return new DetailRequest(List.of(time1, time2, time3, time4, time5, time6, time7), - "지도 url", "존맛탱구리", "01032472601"); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java deleted file mode 100644 index b6ecb0d8..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/CafeControllerTest.java +++ /dev/null @@ -1,470 +0,0 @@ -package com.project.yozmcafe.controller; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_CAFE; -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.groups.Tuple.tuple; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; - -import java.util.List; -import java.util.Objects; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.restdocs.payload.ResponseFieldsSnippet; -import org.springframework.restdocs.request.QueryParametersSnippet; - -import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse; -import com.project.yozmcafe.controller.dto.cafe.CafeResponse; -import com.project.yozmcafe.controller.dto.cafe.CafeSearchResponse; -import com.project.yozmcafe.domain.cafe.Cafe; -import com.project.yozmcafe.domain.cafe.CafeRepository; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.domain.menu.MenuRepository; -import com.project.yozmcafe.fixture.Fixture; - -import io.restassured.response.Response; - -class CafeControllerTest extends BaseControllerTest { - - private static final String MEMBER_ID = "memberId"; - private static final String CAFE_API = "cafeApi/"; - - @Autowired - private MemberRepository memberRepository; - @Autowired - private CafeRepository cafeRepository; - @Autowired - private MenuRepository menuRepository; - private Cafe cafe1, cafe2, cafe3, cafe4, cafe5; - - @BeforeEach - void setUp() { - cafe1 = cafeRepository.save(Fixture.getCafe("n1", "address1", 1)); - cafe2 = cafeRepository.save(Fixture.getCafe("n2", "address2", 2)); - cafe3 = cafeRepository.save(Fixture.getCafe("n3", "address3", 3)); - cafe4 = cafeRepository.save(Fixture.getCafe("n4", "address4", 4)); - } - - @Test - @DisplayName("카페에 좋아요를 추가하고, 해당 카페를 조회하는 경우 isLike가 true로 매핑되어 응답한다.") - void updateLikesAdd() { - //given - doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); - doNothing().when(jwtTokenProvider).validate(anyString()); - saveMemberAndUnViewedCafes(); - - final Response likeResponse = given() - .auth().oauth2("tmpToken") - .when() - .post("/cafes/{cafeId}/likes?isLiked=true", cafe1.getId()); - - //when - final Response response = given() - .auth().oauth2("tmpToken") - .when() - .get("/cafes"); - final List cafeResponses = getCafeResponses(response); - - //then - final CafeResponse cafeResponse = getCafeResponse(cafeResponses, cafe1.getId()); - assertAll( - () -> assertThat(likeResponse.getStatusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).hasSize(4), - () -> assertThat(cafeResponse.likeCount()).isEqualTo(2), - () -> assertThat(cafeResponse.isLiked()).isTrue() - ); - } - - private CafeResponse getCafeResponse(final List cafeResponses, long targetCafeId) { - return cafeResponses.stream() - .filter(response -> Objects.equals(response.id(), targetCafeId)) - .findAny() - .get(); - } - - @Test - @DisplayName("카페에 좋아요를 취소하고, 해당 카페를 조회하는 경우 isLike가 false로 매핑되어 응답한다.") - void updateLikes() { - //given - doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); - doNothing().when(jwtTokenProvider).validate(anyString()); - saveMemberAndUnViewedCafesAndLikedCafes(); - - //when - final Response likeResponse = given().auth().oauth2("tmpToken") - .when() - .post("/cafes/{cafeId}/likes?isLiked=false", cafe1.getId()); - - final Response response = given() - .auth().oauth2("tmpToken") - .when() - .get("/cafes"); - - final List cafeResponses = getCafeResponses(response); - - //then - final CafeResponse cafeResponse = getCafeResponse(cafeResponses, cafe1.getId()); - assertAll( - () -> assertThat(likeResponse.getStatusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).hasSize(4), - () -> assertThat(cafeResponse.likeCount()).isZero(), - () -> assertThat(cafeResponse.isLiked()).isFalse() - ); - } - - @Test - @DisplayName("로그인 되지 않은 사용자가 /cafes/guest?page=? 에 GET요청을 보내면 페이지에 해당하는 서로 다른 카페 정보들을 5개씩 응답한다.") - void getCafesSuccessByUnLoginUser() { - //given - cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 1)); - - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "비회원 사용자 카페 조회", getPageRequestParam(), getCafeResponseFields())) - .when() - .get("/cafes/guest?page=1"); - final List cafeResponses = getCafeResponses(response); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).extracting("id", "name") - .contains(tuple(cafe1.getId(), "n1"), - tuple(cafe2.getId(), "n2"), - tuple(cafe3.getId(), "n3"), - tuple(cafe4.getId(), "n4"), - tuple(cafe5.getId(), "n5")) - ); - } - - @Test - @DisplayName("로그인 되지 않은 사용자가 /cafes/guest?page=? 에 GET요청을 보낸 경우 page가 최대 page를 초과하는 경우 빈배열을 반환한다.") - void getCafesEmptyByUnLoginUser() { - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "비회원 사용자 카페 조회 page가 최대 page를 초과하면 빈 배열 반환", - getPageRequestParam(), - responseFields(fieldWithPath("[]").description("page가 초과하여 빈배열 반환")))) - .when() - .get("/cafes/guest?page=2000"); - - final List cafeResponses = getCafeResponses(response); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).isEmpty() - ); - } - - @Test - @DisplayName("카페 id로 해당하는 카페를 조회한다.") - void findById() { - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "카페 id로 단 건 조회", - pathParameters(parameterWithName("cafeId").description("카페 Id")), - getOneCafeResponseFields())) - .when() - .get("/cafes/{cafeId}", cafe3.getId()); - - //then - final Long resultId = response.then().log().all().extract().jsonPath().getLong("id"); - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(resultId).isEqualTo(cafe3.getId()) - ); - } - - @Test - @DisplayName("카페 id로 해당하는 카페를 조회할 때, 존재하지 않는 카페이면 statusCode 400을 응답한다") - void findByIdWhenNotExist() { - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "카페 id로 단 건 조회 예외", - pathParameters(parameterWithName("cafeId").description("카페 Id")) - )) - .when() - .get("/cafes/{cafeId}", 9999999L); - - //then - final String errorResponseMessage = response.getBody().jsonPath().getString("message"); - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(400), - () -> assertThat(errorResponseMessage).isEqualTo(NOT_EXISTED_CAFE.getMessage()) - ); - } - - @Test - @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보내면 아직 보지 않은 랜덤한, 서로 다른 카페정보를 5개씩 응답한다.") - void getCafesWithMember() { - //given - doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); - doNothing().when(jwtTokenProvider).validate(anyString()); - - final Member member = saveMemberAndUnViewedCafes(); - cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 1)); - member.addUnViewedCafes(List.of(cafe5)); - memberRepository.save(member); - - //when - final Response response = given(spec).log().all() - .auth().oauth2("tmpToken") - .filter(document(CAFE_API + "로그인 한 사용자 카페 조회", getCafeResponseFields())) - .when() - .get("/cafes"); - - //then - final List cafeResponses = getCafeResponses(response); - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).extracting("id", "name") - .contains(tuple(cafe1.getId(), "n1"), - tuple(cafe2.getId(), "n2"), - tuple(cafe3.getId(), "n3"), - tuple(cafe4.getId(), "n4"), - tuple(cafe5.getId(), "n5")) - ); - } - - @Test - @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보낼 때, 아직보지 않은 카페가 5개 미만이면 남은 수만큼의 서로 다른 카페를 응답한다.") - void getCafesWithMemberWhenCafeLessThan() { - //given - doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); - doNothing().when(jwtTokenProvider).validate(anyString()); - saveMemberAndUnViewedCafes(); - - //when - final Response response = given(spec).log().all() - .auth().oauth2("tmpToken") - .filter(document(CAFE_API + "로그인 한 사용자 카페 조회 시 남은 카페가 5개 미만인 경우", getCafeResponseFields())) - .when() - .get("/cafes"); - - final List cafeResponses = getCafeResponses(response); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeResponses).extracting("id", "name") - .contains(tuple(cafe1.getId(), "n1"), - tuple(cafe2.getId(), "n2"), - tuple(cafe3.getId(), "n3"), - tuple(cafe4.getId(), "n4")) - ); - } - - @Test - @DisplayName("/cafes/rank?page=? 요청을 보내면 좋아요 개수가 큰 순으로 페이지에 맞는 카페정보를 응답한다.") - void getCafesOrderByLikeCount() { - //given - final Cafe savedCafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 50)); - final Cafe savedCafe6 = cafeRepository.save(Fixture.getCafe("n6", "address5", 66)); - final Cafe savedCafe7 = cafeRepository.save(Fixture.getCafe("n7", "address5", 67)); - final Cafe savedCafe8 = cafeRepository.save(Fixture.getCafe("n8", "address5", 68)); - final Cafe savedCafe9 = cafeRepository.save(Fixture.getCafe("n9", "address5", 69)); - final Cafe savedCafe10 = cafeRepository.save(Fixture.getCafe("n10", "address5", 70)); - - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회", getPageRequestParam(), - getCafeRankResponseFields())) - .when() - .get("/cafes/ranks?page=1"); - - final List cafeRankResponses = getCafeRankResponses(response); - - //then - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeRankResponses).extracting("id", "rank", "likeCount") - .containsExactly( - tuple(savedCafe10.getId(), 1, savedCafe10.getLikeCount()), - tuple(savedCafe9.getId(), 2, savedCafe9.getLikeCount()), - tuple(savedCafe8.getId(), 3, savedCafe8.getLikeCount()), - tuple(savedCafe7.getId(), 4, savedCafe7.getLikeCount()), - tuple(savedCafe6.getId(), 5, savedCafe6.getLikeCount()), - tuple(savedCafe5.getId(), 6, savedCafe5.getLikeCount()), - tuple(cafe4.getId(), 7, cafe4.getLikeCount()), - tuple(cafe3.getId(), 8, cafe3.getLikeCount()), - tuple(cafe2.getId(), 9, cafe2.getLikeCount()), - tuple(cafe1.getId(), 10, cafe1.getLikeCount()) - ) - ); - } - - @Test - @DisplayName("/cafes/rank?page=? 요청을 보낼 때, 좋아요 된 카페가 존재하지 않으면 빈 배열을 반환한다.") - void getCafesOrderByLikeCountWhenNotExist() { - //given - cafeRepository.save(Fixture.getCafe("n5", "address5", 20)); - - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회 - 카페가 존재하지 않는 경우", getPageRequestParam())) - .when() - .get("/cafes/ranks?page=2"); - - //then - final List cafeRankResponses = getCafeRankResponses(response); - - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeRankResponses).isEmpty() - ); - } - - @Test - @DisplayName("사용자가 검색 요청을 보내면, 검색어와 기준에 맞는 카페를 응답한다.") - void getCafesBySearch() { - //given - menuRepository.save(Fixture.getMenu(cafe1, 1, "요즘커피")); - - //when - final Response response = given(spec).log().all() - .filter(document(CAFE_API + "카페 검색", - getSearchRequestParam(), - getCafeSearchResponseFields())) - .when() - .get("/cafes/search?cafeName=n1&menu=요즘커피&address=address"); - - //then - final List cafeSearchResponses = getCafeSearchResponses(response); - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeSearchResponses).extracting("id", "name") - .containsOnly(tuple(cafe1.getId(), "n1")) - ); - } - - @Test - @DisplayName("사용자가 검색 요청을 보내면, 검색어와 기준에 맞는 카페를 응답한다. - 메뉴 검색하지 않을 경우") - void getCafesBySearchWhenNotSearchMenu() { - //given, when - final Response response = given().log().all() - .when() - .get("/cafes/search?cafeName=n2&address=addr"); - - //then - final List cafeSearchResponses = getCafeSearchResponses(response); - assertAll( - () -> assertThat(response.statusCode()).isEqualTo(200), - () -> assertThat(cafeSearchResponses).extracting("id", "name") - .containsOnly(tuple(cafe2.getId(), "n2")) - ); - } - - private Member saveMemberAndUnViewedCafes() { - final Member member = new Member(MEMBER_ID, "asdf", "img"); - member.addUnViewedCafes(List.of(cafe1, cafe2, cafe3, cafe4)); - return memberRepository.save(member); - } - - private void saveMemberAndUnViewedCafesAndLikedCafes() { - final Member member = new Member(MEMBER_ID, "memberName", "memberImg"); - member.addUnViewedCafes(List.of(cafe1, cafe2, cafe3, cafe4)); - member.updateLikedCafesBy(cafe1, true); - member.updateLikedCafesBy(cafe2, true); - member.updateLikedCafesBy(cafe3, true); - member.updateLikedCafesBy(cafe4, true); - memberRepository.save(member); - } - - private ResponseFieldsSnippet getCafeResponseFields() { - return responseFields( - fieldWithPath("[].id").description("카페 아이디"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 주소"), - fieldWithPath("[].images[]").description("카페 이미지 url"), - fieldWithPath("[].isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), - fieldWithPath("[].likeCount").description("카페의 좋아요 갯수"), - fieldWithPath("[].detail.phone").description("카페의 전화번호"), - fieldWithPath("[].detail.mapUrl").description("카페의 네이버 지도 url"), - fieldWithPath("[].detail.description").description("카페의 상세정보"), - fieldWithPath("[].detail.openingHours[].day").description("요일"), - fieldWithPath("[].detail.openingHours[].open").description("카페 오픈시간"), - fieldWithPath("[].detail.openingHours[].close").description("카페 종료시간"), - fieldWithPath("[].detail.openingHours[].opened").description("카페 해당요일 영업여부") - ); - } - - private ResponseFieldsSnippet getCafeRankResponseFields() { - return responseFields( - fieldWithPath("[].rank").description("카페 순위"), - fieldWithPath("[].id").description("카페 아이디"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 주소"), - fieldWithPath("[].image").description("카페 대표 이미지 url"), - fieldWithPath("[].likeCount").description("카페의 좋아요 갯수") - ); - } - - private ResponseFieldsSnippet getOneCafeResponseFields() { - return responseFields( - fieldWithPath(".id").description("카페 아이디"), - fieldWithPath(".name").description("카페 이름"), - fieldWithPath(".address").description("카페 주소"), - fieldWithPath(".images[]").description("카페 이미지 url"), - fieldWithPath(".isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), - fieldWithPath(".likeCount").description("카페의 좋아요 갯수"), - fieldWithPath(".detail.phone").description("카페의 전화번호"), - fieldWithPath(".detail.mapUrl").description("카페의 네이버 지도 url"), - fieldWithPath(".detail.description").description("카페의 상세정보"), - fieldWithPath(".detail.openingHours[].day").description("요일"), - fieldWithPath(".detail.openingHours[].open").description("카페 오픈시간"), - fieldWithPath(".detail.openingHours[].close").description("카페 종료시간"), - fieldWithPath(".detail.openingHours[].opened").description("카페 해당요일 영업여부") - ); - } - - private List getCafeResponses(final Response response) { - return response.then().log().all() - .extract().jsonPath().getList(".", CafeResponse.class); - } - - private List getCafeSearchResponses(final Response response) { - return response.then().log().all() - .extract().jsonPath().getList(".", CafeSearchResponse.class); - } - - private List getCafeRankResponses(final Response response) { - return response.then().log().all() - .extract().jsonPath().getList(".", CafeRankResponse.class); - } - - private QueryParametersSnippet getPageRequestParam() { - return queryParameters(parameterWithName("page").description("페이지 번호")); - } - - private QueryParametersSnippet getSearchRequestParam() { - return queryParameters( - parameterWithName("cafeName").description("카페명 검색어"), - parameterWithName("menu").description("카페의 메뉴 검색어"), - parameterWithName("address").description("카페의 주소 검색어") - ); - } - - private ResponseFieldsSnippet getCafeSearchResponseFields() { - return responseFields( - fieldWithPath("[].id").description("카페 아이디"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 주소"), - fieldWithPath("[].image").description("카페 대표 이미지 url"), - fieldWithPath("[].likeCount").description("카페의 좋아요 갯수") - ); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/admin/AdminDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/admin/AdminDocuments.java new file mode 100644 index 00000000..32ebf552 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/admin/AdminDocuments.java @@ -0,0 +1,81 @@ +package com.project.yozmcafe.controller.admin; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestPartBody; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class AdminDocuments { + + public static RestDocumentationFilter adminCafeSaveDocument() { + return document("어드민 API/카페 저장하기", + requestPartBody("request"), requestPartBody("images"), + responseHeaders(headerWithName("Location").description("카페 저장 위치"))); + } + + public static RestDocumentationFilter adminCafeUpdateDocument() { + return document("어드민 API/카페 업데이트하기", + requestPartBody("request"), requestPartBody("images"), + pathParameters(parameterWithName("cafeId").description("업데이트할 카페 ID"))); + } + + public static RestDocumentationFilter adminCafeRemoveDocument() { + return document("어드민 API/카페 삭제하기", + pathParameters(parameterWithName("cafeId").description("삭제할 카페 ID"))); + } + + public static RestDocumentationFilter adminAllCafesFindDocument() { + return document("어드민 API/카페 전체 조회하기", + responseFields( + fieldWithPath("[].id").description("카페 ID"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 도로명 주소"), + fieldWithPath("[].isLiked").description("좋아요 누른 여부"), + fieldWithPath("[].likeCount").description("좋아요 숫자"), + fieldWithPath("[].images.[]").description("이미지 URL 배열"), + fieldWithPath("[].detail.mapUrl").description("네이버 지도 URL"), + fieldWithPath("[].detail.description").description("상세 설명"), + fieldWithPath("[].detail.phone").description("전화번호"), + fieldWithPath("[].detail.openingHours.[].day").description("요일"), + fieldWithPath("[].detail.openingHours.[].open").description("영업 시작 시각"), + fieldWithPath("[].detail.openingHours.[].close").description("영업 종료 시각"), + fieldWithPath("[].detail.openingHours.[].opened").description("해당 요일 영업 여부"))); + } + + public static RestDocumentationFilter adminCafeFindDocument() { + return document("어드민 API/카페 단건 조회하기", + pathParameters(parameterWithName("cafeId").description("조회할 카페 ID")), + responseFields( + fieldWithPath("id").description("카페 ID"), + fieldWithPath("name").description("카페 이름"), + fieldWithPath("address").description("카페 도로명 주소"), + fieldWithPath("isLiked").description("좋아요 누른 여부"), + fieldWithPath("likeCount").description("좋아요 숫자"), + fieldWithPath("images.[]").description("이미지 URL 배열"), + fieldWithPath("detail.mapUrl").description("네이버 지도 URL"), + fieldWithPath("detail.description").description("상세 설명"), + fieldWithPath("detail.phone").description("전화번호"), + fieldWithPath("detail.openingHours.[].day").description("요일"), + fieldWithPath("detail.openingHours.[].open").description("영업 시작 시각"), + fieldWithPath("detail.openingHours.[].close").description("영업 종료 시각"), + fieldWithPath("detail.openingHours.[].opened").description("해당 요일 영업 여부")) + ); + } + + public static RestDocumentationFilter adminLocationSaveDocument() { + return document("어드민 API/좌표 정보 저장", + pathParameters(parameterWithName("cafeId").description("죄표를 추가할 카페 ID")), + requestFields( + fieldWithPath("latitude").description("위도"), + fieldWithPath("longitude").description("경도") + ), + responseHeaders(headerWithName("Location").description("카페 저장 위치"))); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java new file mode 100644 index 00000000..68f9113c --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java @@ -0,0 +1,205 @@ +package com.project.yozmcafe.controller.admin; + +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminAllCafesFindDocument; +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminCafeFindDocument; +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminCafeRemoveDocument; +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminCafeSaveDocument; +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminCafeUpdateDocument; +import static com.project.yozmcafe.controller.admin.AdminDocuments.adminLocationSaveDocument; +import static io.restassured.http.ContentType.JSON; +import static io.restassured.http.ContentType.MULTIPART; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.springframework.http.HttpStatus.CREATED; +import static org.springframework.http.HttpStatus.NO_CONTENT; +import static org.springframework.http.HttpStatus.OK; + +import java.io.File; +import java.time.LocalTime; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.multipart.MultipartFile; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; +import com.project.yozmcafe.controller.dto.cafe.CafeCoordinateRequest; +import com.project.yozmcafe.controller.dto.cafe.CafeRequest; +import com.project.yozmcafe.controller.dto.cafe.CafeUpdateRequest; +import com.project.yozmcafe.controller.dto.cafe.DetailRequest; +import com.project.yozmcafe.domain.cafe.available.Days; + +import io.restassured.response.Response; + +class CafeAdminControllerTest extends BaseControllerTest { + + @Autowired + private ObjectMapper mapper; + + private File image = new File("src/test/resources/image.png"); + + @Test + @DisplayName("카페 저장하기") + void save() { + //given + doNothing().when(s3Client).upload(any(MultipartFile.class)); + final String cafeRequestJson = makeCafeRequest(); + + //when, then + final Response response = customGivenWithDocs(adminCafeSaveDocument()) + .contentType(MULTIPART) + .multiPart("request", cafeRequestJson, "application/json") + .multiPart("images", image, "image/png") + .accept(JSON) + .post("/admin/cafes"); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(CREATED.value()); + assertThat(response.header("Location")).isNotNull(); + }); + } + + @Test + @DisplayName("카페 업데이트") + void update() { + //given + doNothing().when(s3Client).upload(any(MultipartFile.class)); + doNothing().when(s3Client).delete(anyString()); + String location = saveCafe(); + String updateRequest = makeCafeUpdateRequest(); + + //when + final Response response = customGivenWithDocs(adminCafeUpdateDocument()) + .contentType(MULTIPART) + .multiPart("request", updateRequest, "application/json") + .multiPart("images", image, "image/png") + .accept(JSON) + .put("/admin/cafes/{cafeId}", location); + + //then + assertThat(response.statusCode()).isEqualTo(NO_CONTENT.value()); + } + + @Test + @DisplayName("카페 삭제") + void delete() { + //given + doNothing().when(s3Client).delete(anyString()); + String location = saveCafe(); + + //when + final Response response = customGivenWithDocs(adminCafeRemoveDocument()) + .delete("/admin/cafes/{cafeId}", location); + + //then + assertThat(response.statusCode()).isEqualTo(NO_CONTENT.value()); + } + + @Test + @DisplayName("카페 전체 조회") + void findAll() { + //given + saveCafe(); + saveCafe(); + + //when, then + final Response response = customGivenWithDocs(adminAllCafesFindDocument()) + .get("/admin/cafes"); + + assertThat(response.statusCode()).isEqualTo(OK.value()); + } + + @Test + @DisplayName("카페 단건 조회") + void findById() { + //given + String location = saveCafe(); + + //when + final Response response = customGivenWithDocs(adminCafeFindDocument()) + .get("/admin/cafes/{cafeId}", location); + + //then + assertThat(response.statusCode()).isEqualTo(OK.value()); + } + + @Test + @DisplayName("좌표 정보를 저장한다.") + void saveCoordinate() { + //given + final String location = saveCafe(); + + //when + final Response response = customGivenWithDocs(adminLocationSaveDocument()) + .body(new CafeCoordinateRequest(20, 10)) + .post("/admin/cafes/{cafeId}/coordinate", location); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(CREATED.value()); + assertThat(response.header("Location")).isNotNull(); + }); + } + + private String saveCafe() { + doNothing().when(s3Client).upload(any(MultipartFile.class)); + final String cafeRequest = makeCafeRequest(); + + final String location = customGiven() + .contentType(MULTIPART) + .multiPart("request", cafeRequest, "application/json") + .multiPart("images", image, "image/png") + .accept(JSON) + .when() + .post("/admin/cafes") + .then() + .extract().header("Location"); + + String[] split = location.split("/"); + + return split[split.length - 1]; + } + + private String makeCafeRequest() { + try { + return mapper.writeValueAsString(new CafeRequest("연어카페", "광안리", detail())); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private String makeCafeUpdateRequest() { + try { + return mapper.writeValueAsString(new CafeUpdateRequest("참치전문점", "해운대", detail(), 100)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private DetailRequest detail() { + final AvailableTimeRequest time1 = new AvailableTimeRequest(Days.MONDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time2 = new AvailableTimeRequest(Days.TUESDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time3 = new AvailableTimeRequest(Days.WEDNESDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time4 = new AvailableTimeRequest(Days.THURSDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time5 = new AvailableTimeRequest(Days.FRIDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time6 = new AvailableTimeRequest(Days.SATURDAY, LocalTime.now(), LocalTime.now(), + true); + final AvailableTimeRequest time7 = new AvailableTimeRequest(Days.SUNDAY, LocalTime.now(), LocalTime.now(), + true); + + return new DetailRequest(List.of(time1, time2, time3, time4, time5, time6, time7), + "지도 url", "존맛탱구리", "01032472601"); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeControllerTest.java new file mode 100644 index 00000000..49876a06 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeControllerTest.java @@ -0,0 +1,357 @@ +package com.project.yozmcafe.controller.cafe; + +import static com.project.yozmcafe.controller.cafe.CafeDocuments.cafeEmptyRankingDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.cafeLikeCountRankingDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.cafeSearchDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.findCafeDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.findCafeNotFoundDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.guestCafesDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.guestOverFlowPageCafeDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.memberFindCafesDocument; +import static com.project.yozmcafe.controller.cafe.CafeDocuments.memberFindCafesLessThanFiveDocument; +import static com.project.yozmcafe.exception.ErrorCode.NOT_EXISTED_CAFE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.assertj.core.groups.Tuple.tuple; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; + +import java.util.List; +import java.util.Objects; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.controller.dto.cafe.CafeRankResponse; +import com.project.yozmcafe.controller.dto.cafe.CafeResponse; +import com.project.yozmcafe.controller.dto.cafe.CafeSearchResponse; +import com.project.yozmcafe.domain.cafe.Cafe; +import com.project.yozmcafe.domain.cafe.CafeRepository; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.domain.menu.MenuRepository; +import com.project.yozmcafe.fixture.Fixture; + +import io.restassured.response.Response; + +class CafeControllerTest extends BaseControllerTest { + + private static final String MEMBER_ID = "memberId"; + + @Autowired + private MemberRepository memberRepository; + @Autowired + private CafeRepository cafeRepository; + @Autowired + private MenuRepository menuRepository; + private Cafe cafe1, cafe2, cafe3, cafe4, cafe5; + + @BeforeEach + void setUp() { + cafe1 = cafeRepository.save(Fixture.getCafe("n1", "address1", 1)); + cafe2 = cafeRepository.save(Fixture.getCafe("n2", "address2", 2)); + cafe3 = cafeRepository.save(Fixture.getCafe("n3", "address3", 3)); + cafe4 = cafeRepository.save(Fixture.getCafe("n4", "address4", 4)); + } + + @Test + @DisplayName("카페에 좋아요를 추가하고, 해당 카페를 조회하는 경우 isLike가 true로 매핑되어 응답한다.") + void updateLikesAdd() { + //given + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); + saveMemberAndUnViewedCafes(); + + //when + final Response likeResponse = customGiven() + .auth().oauth2("tmpToken") + .post("/cafes/{cafeId}/likes?isLiked=true", cafe1.getId()); + + final Response response = customGiven() + .auth().oauth2("tmpToken") + .get("/cafes"); + + //then + final List cafeResponses = getCafeResponses(response); + final CafeResponse cafeResponse = getCafeResponse(cafeResponses, cafe1.getId()); + + assertSoftly(softAssertions -> { + assertThat(likeResponse.getStatusCode()).isEqualTo(200); + assertThat(cafeResponses).hasSize(4); + assertThat(cafeResponse.likeCount()).isEqualTo(2); + assertThat(cafeResponse.isLiked()).isTrue(); + }); + } + + private CafeResponse getCafeResponse(final List cafeResponses, long targetCafeId) { + return cafeResponses.stream() + .filter(response -> Objects.equals(response.id(), targetCafeId)) + .findAny() + .get(); + } + + @Test + @DisplayName("카페에 좋아요를 취소하고, 해당 카페를 조회하는 경우 isLike가 false로 매핑되어 응답한다.") + void updateLikes() { + //given + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); + saveMemberAndUnViewedCafesAndLikedCafes(); + + //when + final Response likeResponse = customGiven() + .auth().oauth2("tmpToken") + .post("/cafes/{cafeId}/likes?isLiked=false", cafe1.getId()); + + final Response response = customGiven() + .auth().oauth2("tmpToken") + .get("/cafes"); + + //then + final List cafeResponses = getCafeResponses(response); + final CafeResponse cafeResponse = getCafeResponse(cafeResponses, cafe1.getId()); + + assertSoftly(softAssertions -> { + assertThat(likeResponse.getStatusCode()).isEqualTo(200); + assertThat(cafeResponses).hasSize(4); + assertThat(cafeResponse.likeCount()).isZero(); + assertThat(cafeResponse.isLiked()).isFalse(); + }); + } + + @Test + @DisplayName("로그인 되지 않은 사용자가 /cafes/guest?page=? 에 GET요청을 보내면 페이지에 해당하는 서로 다른 카페 정보들을 5개씩 응답한다.") + void getCafesSuccessByUnLoginUser() { + //given + cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 1)); + + //when + final Response response = customGivenWithDocs(guestCafesDocument()) + .queryParam("page", 1) + .get("/cafes/guest"); + + //then + final List cafeResponses = getCafeResponses(response); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeResponses).extracting("id") + .contains(cafe1.getId(), cafe2.getId(), cafe3.getId(), cafe4.getId(), cafe5.getId()); + }); + } + + @Test + @DisplayName("로그인 되지 않은 사용자가 /cafes/guest?page=? 에 GET요청을 보낸 경우 page가 최대 page를 초과하는 경우 빈배열을 반환한다.") + void getCafesEmptyByUnLoginUser() { + //when + final Response response = customGivenWithDocs(guestOverFlowPageCafeDocument()) + .get("/cafes/guest?page=2000"); + + //then + final List cafeResponses = getCafeResponses(response); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeResponses).isEmpty(); + }); + } + + @Test + @DisplayName("카페 id로 해당하는 카페를 조회한다.") + void findById() { + //when + final Response response = customGivenWithDocs(findCafeDocument()) + .get("/cafes/{cafeId}", cafe3.getId()); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.jsonPath().getLong("id")).isEqualTo(cafe3.getId()); + }); + } + + @Test + @DisplayName("카페 id로 해당하는 카페를 조회할 때, 존재하지 않는 카페이면 statusCode 400을 응답한다") + void findByIdWhenNotExist() { + //when + final Response response = customGivenWithDocs(findCafeNotFoundDocument()) + .get("/cafes/{cafeId}", 9999999L); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(400); + assertThat(response.jsonPath().getString("message")).isEqualTo(NOT_EXISTED_CAFE.getMessage()); + }); + } + + @Test + @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보내면 아직 보지 않은 랜덤한, 서로 다른 카페정보를 5개씩 응답한다.") + void getCafesWithMember() { + //given + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); + + addFiveUnViewedCafes(); + + //when + final Response response = customGivenWithDocs(memberFindCafesDocument()) + .auth().oauth2("tmpToken") + .get("/cafes"); + + //then + final List cafeResponses = getCafeResponses(response); + + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeResponses).extracting("id") + .contains(cafe1.getId(), cafe2.getId(), cafe3.getId(), cafe4.getId(), cafe5.getId()); + + }); + } + + @Test + @DisplayName("로그인한 사용자가 /cafes 에 GET 요청을 보낼 때, 아직보지 않은 카페가 5개 미만이면 남은 수만큼의 서로 다른 카페를 응답한다.") + void getCafesWithMemberWhenCafeLessThan() { + //given + doReturn(MEMBER_ID).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); + saveMemberAndUnViewedCafes(); + + //when + final Response response = customGivenWithDocs(memberFindCafesLessThanFiveDocument()) + .auth().oauth2("tmpToken") + .get("/cafes"); + + //then + final List cafeResponses = getCafeResponses(response); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeResponses).extracting("id") + .contains(cafe1.getId(), cafe2.getId(), cafe3.getId(), cafe4.getId()); + }); + } + + @Test + @DisplayName("/cafes/rank?page=? 요청을 보내면 좋아요 개수가 큰 순으로 페이지에 맞는 카페정보를 응답한다.") + void getCafesOrderByLikeCount() { + //given + final Cafe cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 50)); + final Cafe cafe6 = cafeRepository.save(Fixture.getCafe("n6", "address5", 66)); + final Cafe cafe7 = cafeRepository.save(Fixture.getCafe("n7", "address5", 67)); + final Cafe cafe8 = cafeRepository.save(Fixture.getCafe("n8", "address5", 68)); + final Cafe cafe9 = cafeRepository.save(Fixture.getCafe("n9", "address5", 69)); + final Cafe cafe10 = cafeRepository.save(Fixture.getCafe("n10", "address5", 70)); + + //when + final Response response = customGivenWithDocs(cafeLikeCountRankingDocument()) + .get("/cafes/ranks?page=1"); + + final List cafeRankResponses = getCafeRankResponses(response); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeRankResponses).extracting("id") + .containsExactly(cafe10.getId(), cafe9.getId(), cafe8.getId(), cafe7.getId(), cafe6.getId(), + cafe5.getId(), cafe4.getId(), cafe3.getId(), cafe2.getId(), cafe1.getId() + ); + }); + } + + @Test + @DisplayName("/cafes/rank?page=? 요청을 보낼 때, 좋아요 된 카페가 존재하지 않으면 빈 배열을 반환한다.") + void getCafesOrderByLikeCountWhenNotExist() { + //given + cafeRepository.save(Fixture.getCafe("n5", "address5", 20)); + + //when + final Response response = customGivenWithDocs(cafeEmptyRankingDocument()) + .get("/cafes/ranks?page=2"); + + //then + final List cafeRankResponses = getCafeRankResponses(response); + + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeRankResponses).isEmpty(); + }); + } + + @Test + @DisplayName("사용자가 검색 요청을 보내면, 검색어와 기준에 맞는 카페를 응답한다.") + void getCafesBySearch() { + //given + menuRepository.save(Fixture.getMenu(cafe1, 1, "요즘커피")); + + //when + final Response response = customGivenWithDocs(cafeSearchDocument()) + .queryParam("cafeName", "n1") + .queryParam("menu", "요즘커피") + .queryParam("address", "address") + .get("/cafes/search"); + + //then + final List cafeSearchResponses = getCafeSearchResponses(response); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(cafeSearchResponses).extracting("id") + .containsOnly(cafe1.getId()); + }); + } + + @Test + @DisplayName("사용자가 검색 요청을 보내면, 검색어와 기준에 맞는 카페를 응답한다. - 메뉴 검색하지 않을 경우") + void getCafesBySearchWhenNotSearchMenu() { + //given, when + final Response response = customGiven() + .queryParam("cafeName", "n2") + .queryParam("address", "address") + .get("/cafes/search"); + + //then + final List cafeSearchResponses = getCafeSearchResponses(response); + assertAll( + () -> assertThat(response.statusCode()).isEqualTo(200), + () -> assertThat(cafeSearchResponses).extracting("id", "name") + .containsOnly(tuple(cafe2.getId(), "n2")) + ); + } + + private void addFiveUnViewedCafes() { + final Member member = saveMemberAndUnViewedCafes(); + cafe5 = cafeRepository.save(Fixture.getCafe("n5", "address5", 1)); + member.addUnViewedCafes(List.of(cafe5)); + memberRepository.save(member); + } + + private Member saveMemberAndUnViewedCafes() { + final Member member = new Member(MEMBER_ID, "asdf", "img"); + member.addUnViewedCafes(List.of(cafe1, cafe2, cafe3, cafe4)); + return memberRepository.save(member); + } + + private void saveMemberAndUnViewedCafesAndLikedCafes() { + final Member member = new Member(MEMBER_ID, "memberName", "memberImg"); + member.addUnViewedCafes(List.of(cafe1, cafe2, cafe3, cafe4)); + member.updateLikedCafesBy(cafe1, true); + member.updateLikedCafesBy(cafe2, true); + member.updateLikedCafesBy(cafe3, true); + member.updateLikedCafesBy(cafe4, true); + memberRepository.save(member); + } + + private List getCafeResponses(final Response response) { + return response.jsonPath().getList(".", CafeResponse.class); + } + + private List getCafeSearchResponses(final Response response) { + return response.jsonPath().getList(".", CafeSearchResponse.class); + } + + private List getCafeRankResponses(final Response response) { + return response.jsonPath().getList(".", CafeRankResponse.class); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeDocuments.java new file mode 100644 index 00000000..18cb6aa4 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/cafe/CafeDocuments.java @@ -0,0 +1,115 @@ +package com.project.yozmcafe.controller.cafe; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; + +import org.springframework.restdocs.payload.ResponseFieldsSnippet; +import org.springframework.restdocs.request.QueryParametersSnippet; +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class CafeDocuments { + + private static final String CAFE_API = "cafeApi/"; + + public static RestDocumentationFilter guestCafesDocument() { + return document(CAFE_API + "비회원 사용자 카페 조회", getPageRequestParam(), getCafeResponseFields()); + } + + public static RestDocumentationFilter guestOverFlowPageCafeDocument() { + return document(CAFE_API + "비회원 사용자 카페 조회 page가 최대 page를 초과하면 빈 배열 반환", + getPageRequestParam(), + responseFields(fieldWithPath("[]").description("page가 초과하여 빈배열 반환"))); + } + + public static RestDocumentationFilter findCafeDocument() { + return document(CAFE_API + "카페 id로 단 건 조회", + pathParameters(parameterWithName("cafeId").description("카페 Id")), + responseFields( + fieldWithPath(".id").description("카페 아이디"), + fieldWithPath(".name").description("카페 이름"), + fieldWithPath(".address").description("카페 주소"), + fieldWithPath(".images[]").description("카페 이미지 url"), + fieldWithPath(".isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), + fieldWithPath(".likeCount").description("카페의 좋아요 갯수"), + fieldWithPath(".detail.phone").description("카페의 전화번호"), + fieldWithPath(".detail.mapUrl").description("카페의 네이버 지도 url"), + fieldWithPath(".detail.description").description("카페의 상세정보"), + fieldWithPath(".detail.openingHours[].day").description("요일"), + fieldWithPath(".detail.openingHours[].open").description("카페 오픈시간"), + fieldWithPath(".detail.openingHours[].close").description("카페 종료시간"), + fieldWithPath(".detail.openingHours[].opened").description("카페 해당요일 영업여부") + ) + ); + } + + public static RestDocumentationFilter findCafeNotFoundDocument() { + return document(CAFE_API + "카페 id로 단 건 조회 예외", + pathParameters(parameterWithName("cafeId").description("카페 Id"))); + } + + public static RestDocumentationFilter memberFindCafesDocument() { + return document(CAFE_API + "로그인 한 사용자 카페 조회", getCafeResponseFields()); + } + + public static RestDocumentationFilter memberFindCafesLessThanFiveDocument() { + return document(CAFE_API + "로그인 한 사용자 카페 조회 시 남은 카페가 5개 미만인 경우", getCafeResponseFields()); + } + + public static RestDocumentationFilter cafeLikeCountRankingDocument() { + return document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회", + getPageRequestParam(), + responseFields( + fieldWithPath("[].rank").description("카페 순위"), + fieldWithPath("[].id").description("카페 아이디"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 주소"), + fieldWithPath("[].image").description("카페 대표 이미지 url"), + fieldWithPath("[].likeCount").description("카페의 좋아요 갯수") + ) + ); + } + + public static RestDocumentationFilter cafeEmptyRankingDocument() { + return document(CAFE_API + "좋아요 개수 순위에 따라 카페정보 조회 - 카페가 존재하지 않는 경우", getPageRequestParam()); + } + + public static RestDocumentationFilter cafeSearchDocument() { + return document(CAFE_API + "카페 검색", + queryParameters( + parameterWithName("cafeName").description("카페명 검색어"), + parameterWithName("menu").description("카페의 메뉴 검색어"), + parameterWithName("address").description("카페의 주소 검색어")), + responseFields( + fieldWithPath("[].id").description("카페 아이디"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 주소"), + fieldWithPath("[].image").description("카페 대표 이미지 url"), + fieldWithPath("[].likeCount").description("카페의 좋아요 갯수"))); + } + + private static QueryParametersSnippet getPageRequestParam() { + return queryParameters(parameterWithName("page").description("페이지 번호")); + } + + private static ResponseFieldsSnippet getCafeResponseFields() { + return responseFields( + fieldWithPath("[].id").description("카페 아이디"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 주소"), + fieldWithPath("[].images[]").description("카페 이미지 url"), + fieldWithPath("[].isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), + fieldWithPath("[].likeCount").description("카페의 좋아요 갯수"), + fieldWithPath("[].detail.phone").description("카페의 전화번호"), + fieldWithPath("[].detail.mapUrl").description("카페의 네이버 지도 url"), + fieldWithPath("[].detail.description").description("카페의 상세정보"), + fieldWithPath("[].detail.openingHours[].day").description("요일"), + fieldWithPath("[].detail.openingHours[].open").description("카페 오픈시간"), + fieldWithPath("[].detail.openingHours[].close").description("카페 종료시간"), + fieldWithPath("[].detail.openingHours[].opened").description("카페 해당요일 영업여부") + ); + } +} From 831d18d89755700ecbb5f1e059ad23ae3a288f30 Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 17:48:38 +0900 Subject: [PATCH 06/10] =?UTF-8?q?test:=20LikedCafeControllerTest=20CustomG?= =?UTF-8?q?iven=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/LikedCafeControllerTest.java | 176 ------------------ .../controller/like/LikeCafeDocuments.java | 48 +++++ .../like/LikedCafeControllerTest.java | 135 ++++++++++++++ 3 files changed, 183 insertions(+), 176 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/like/LikeCafeDocuments.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/like/LikedCafeControllerTest.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java deleted file mode 100644 index 3a2ac284..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/LikedCafeControllerTest.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.project.yozmcafe.controller; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.groups.Tuple.tuple; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; - -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.restdocs.payload.ResponseFieldsSnippet; - -import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse; -import com.project.yozmcafe.domain.cafe.Cafe; -import com.project.yozmcafe.domain.cafe.CafeRepository; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import com.project.yozmcafe.fixture.Fixture; - -import io.restassured.response.Response; - -class LikedCafeControllerTest extends BaseControllerTest { - - @Autowired - private MemberRepository memberRepository; - @Autowired - private CafeRepository cafeRepository; - - @Test - @DisplayName("사용자가 좋아요 한 카페들의 대표 이미지들을 조회한다.") - void getLikedCafes() { - //given - final Cafe savedCafe1 = cafeRepository.save(Fixture.getCafe("오션의 귀여운 카페", "인천 오션동", 5)); - final Cafe savedCafe2 = cafeRepository.save(Fixture.getCafe("오션의 귀여운 카페", "인천 오션동", 5)); - final Member member = new Member("1234", "오션", "오션.img"); - member.updateLikedCafesBy(savedCafe1, true); - member.updateLikedCafesBy(savedCafe2, true); - memberRepository.save(member); - - //when - final Response response = given(spec).log().all() - .filter(document("likedCafe/좋아요 카페 대표 이미지 목록 조회", - queryParameters(parameterWithName("page").description("좋아요 목록 페이지 번호")), - pathParameters(parameterWithName("memberId").description("멤버 ID")), - responseFields(fieldWithPath("[].cafeId").description("카페 ID"), - fieldWithPath("[].imageUrl").description("카페 대표 사진")))) - .when() - .get("/members/{memberId}/liked-cafes?page=1", member.getId()); - - //then - assertAll( - () -> assertThat(response.jsonPath().getLong("[0].cafeId")).isEqualTo(savedCafe2.getId()), - () -> assertThat(response.jsonPath().getLong("[1].cafeId")).isEqualTo(savedCafe1.getId()) - ); - } - - @Test - @DisplayName("멤버의 빈 좋아요한 카페 대표 이미지들을 조회한다.") - void getLikedCafes_empty() { - //given - final Member member = new Member("1", "오션", "오션.img"); - memberRepository.save(member); - - //when - final Response response = given().log().all() - .when() - .get("/members/{memberId}/liked-cafes?page=1", member.getId()); - - //then - assertThat(response.jsonPath().getList("")).isEmpty(); - } - - @Test - @DisplayName("사용자가 카페에 대해 좋아요를 할 수 있다.") - void updateLikes() { - //given - final Member member = memberRepository.save( - new Member("123", "오션", "오션사진")); - final Cafe cafe = cafeRepository.save(Fixture.getCafe(1L, "카페1", "주소1", 10)); - doReturn(member.getId()).when(jwtTokenProvider).getMemberId(anyString()); - doNothing().when(jwtTokenProvider).validate(anyString()); - - //when - final Response response = given(spec).log().all() - .filter(document("likedCafe/좋아요", - queryParameters( - parameterWithName("isLiked").description("true 일 경우 좋아요 추가, false 일 경우 좋아요 취소")), - pathParameters(parameterWithName("cafeId").description("카페 ID")))) - .auth().oauth2("accessToken") - .post("/cafes/{cafeId}/likes?isLiked=true", cafe.getId()); - - //then - response.then() - .statusCode(HttpStatus.OK.value()); - } - - @Test - @DisplayName("사용자의 좋아요 카페 목록의 카페들을 조회한다.") - void getLikedCafeDetails() { - //given - final Cafe savedCafe1 = cafeRepository.save(Fixture.getCafe("카페1", "1동", 5)); - final Cafe savedCafe2 = cafeRepository.save(Fixture.getCafe("카페2", "2동", 5)); - cafeRepository.save(Fixture.getCafe("카페3", "3동", 7)); - final Member member = new Member("1234", "도치", "도치.img"); - member.updateLikedCafesBy(savedCafe1, true); - member.updateLikedCafesBy(savedCafe2, true); - Member savedMember = memberRepository.save(member); - - //when - final Response response = given(spec).log().all() - .filter(document("likedCafe/좋아요 목록의 카페 조회", - pathParameters(parameterWithName("memberId").description("멤버 ID")), - getCafeResponseFields())) - .when() - .get("/members/{memberId}/liked-cafes/details", savedMember.getId()); - - //then - List cafeDetailResponses = getCafeDetailResponses(response); - - assertThat(cafeDetailResponses).extracting("id", "name") - .containsExactly(tuple(savedCafe2.getId(), savedCafe2.getName()), - tuple(savedCafe1.getId(), savedCafe1.getName()) - ); - } - - @Test - @DisplayName("사용자의 빈 좋아요 카페 목록의 카페들을 조회한다.") - void getLikedCafeDetailsWhenEmpty() { - //given - cafeRepository.save(Fixture.getCafe("카페1", "1동", 5)); - final Member savedMember = memberRepository.save(new Member("1234", "도치", "도치.img")); - - //when - final Response response = given().log().all() - .when() - .get("/members/{memberId}/liked-cafes/details", savedMember.getId()); - - //then - assertThat(response.jsonPath().getList("")).isEmpty(); - } - - private ResponseFieldsSnippet getCafeResponseFields() { - return responseFields( - fieldWithPath("[].id").description("카페 아이디"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 주소"), - fieldWithPath("[].images[]").description("카페 이미지 url"), - fieldWithPath("[].isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), - fieldWithPath("[].likeCount").description("카페의 좋아요 갯수"), - fieldWithPath("[].detail.phone").description("카페의 전화번호"), - fieldWithPath("[].detail.mapUrl").description("카페의 네이버 지도 url"), - fieldWithPath("[].detail.description").description("카페의 상세정보"), - fieldWithPath("[].detail.openingHours[].day").description("요일"), - fieldWithPath("[].detail.openingHours[].open").description("카페 오픈시간"), - fieldWithPath("[].detail.openingHours[].close").description("카페 종료시간"), - fieldWithPath("[].detail.openingHours[].opened").description("카페 해당요일 영업여부") - ); - } - - private List getCafeDetailResponses(final Response response) { - return response.then().log().all() - .extract().jsonPath().getList(".", LikedCafeResponse.class); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/like/LikeCafeDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/like/LikeCafeDocuments.java new file mode 100644 index 00000000..ee3ebea5 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/like/LikeCafeDocuments.java @@ -0,0 +1,48 @@ +package com.project.yozmcafe.controller.like; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class LikeCafeDocuments { + + public static RestDocumentationFilter findLikeCafesDocument() { + return document("likedCafe/좋아요 카페 대표 이미지 목록 조회", + queryParameters(parameterWithName("page").description("좋아요 목록 페이지 번호")), + pathParameters(parameterWithName("memberId").description("멤버 ID")), + responseFields(fieldWithPath("[].cafeId").description("카페 ID"), + fieldWithPath("[].imageUrl").description("카페 대표 사진"))); + } + + public static RestDocumentationFilter memberUpdateLikeDocument() { + return document("likedCafe/좋아요", + queryParameters( + parameterWithName("isLiked").description("true 일 경우 좋아요 추가, false 일 경우 좋아요 취소")), + pathParameters(parameterWithName("cafeId").description("카페 ID"))); + } + + public static RestDocumentationFilter likedCafeOfMemberDocument() { + return document("likedCafe/좋아요 목록의 카페 조회", + pathParameters(parameterWithName("memberId").description("멤버 ID")), + responseFields( + fieldWithPath("[].id").description("카페 아이디"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 주소"), + fieldWithPath("[].images[]").description("카페 이미지 url"), + fieldWithPath("[].isLiked").description("해당 카페의 좋아요 여부(비회원은 default = false)"), + fieldWithPath("[].likeCount").description("카페의 좋아요 갯수"), + fieldWithPath("[].detail.phone").description("카페의 전화번호"), + fieldWithPath("[].detail.mapUrl").description("카페의 네이버 지도 url"), + fieldWithPath("[].detail.description").description("카페의 상세정보"), + fieldWithPath("[].detail.openingHours[].day").description("요일"), + fieldWithPath("[].detail.openingHours[].open").description("카페 오픈시간"), + fieldWithPath("[].detail.openingHours[].close").description("카페 종료시간"), + fieldWithPath("[].detail.openingHours[].opened").description("카페 해당요일 영업여부") + )); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/like/LikedCafeControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/like/LikedCafeControllerTest.java new file mode 100644 index 00000000..ad52829a --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/like/LikedCafeControllerTest.java @@ -0,0 +1,135 @@ +package com.project.yozmcafe.controller.like; + +import static com.project.yozmcafe.controller.like.LikeCafeDocuments.findLikeCafesDocument; +import static com.project.yozmcafe.controller.like.LikeCafeDocuments.likedCafeOfMemberDocument; +import static com.project.yozmcafe.controller.like.LikeCafeDocuments.memberUpdateLikeDocument; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.springframework.http.HttpStatus.OK; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.controller.dto.cafe.LikedCafeResponse; +import com.project.yozmcafe.domain.cafe.Cafe; +import com.project.yozmcafe.domain.cafe.CafeRepository; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; +import com.project.yozmcafe.fixture.Fixture; + +import io.restassured.response.Response; + +class LikedCafeControllerTest extends BaseControllerTest { + + @Autowired + private MemberRepository memberRepository; + @Autowired + private CafeRepository cafeRepository; + + private Cafe cafe1, cafe2; + + @BeforeEach + void setUp() { + cafe1 = cafeRepository.save(Fixture.getCafe("오션의 귀여운 카페", "인천 오션동", 5)); + cafe2 = cafeRepository.save(Fixture.getCafe("오션의 귀여운 카페", "인천 오션동", 5)); + } + + @Test + @DisplayName("사용자가 좋아요 한 카페들의 대표 이미지들을 조회한다.") + void getLikedCafes() { + //given + final Member member = new Member("1234", "오션", "오션.img"); + member.updateLikedCafesBy(cafe1, true); + member.updateLikedCafesBy(cafe2, true); + memberRepository.save(member); + + //when + final Response response = customGivenWithDocs(findLikeCafesDocument()) + .queryParam("page", 1) + .get("/members/{memberId}/liked-cafes", member.getId()); + + //then + assertSoftly(softAssertions -> { + assertThat(response.jsonPath().getLong("[0].cafeId")).isEqualTo(cafe2.getId()); + assertThat(response.jsonPath().getLong("[1].cafeId")).isEqualTo(cafe1.getId()); + }); + } + + @Test + @DisplayName("멤버의 빈 좋아요한 카페 대표 이미지들을 조회한다.") + void getLikedCafes_empty() { + //given + final Member member = memberRepository.save(new Member("1", "오션", "오션.img")); + + //when + final Response response = customGiven() + .queryParam("page", 1) + .get("/members/{memberId}/liked-cafes", member.getId()); + + //then + assertThat(response.jsonPath().getList("")).isEmpty(); + } + + @Test + @DisplayName("사용자가 카페에 대해 좋아요를 할 수 있다.") + void updateLikes() { + //given + final Member member = memberRepository.save(new Member("123", "오션", "오션사진")); + doReturn(member.getId()).when(jwtTokenProvider).getMemberId(anyString()); + doNothing().when(jwtTokenProvider).validate(anyString()); + + //when + final Response response = customGivenWithDocs(memberUpdateLikeDocument()) + .queryParam("isLiked", true) + .auth().oauth2("accessToken") + .post("/cafes/{cafeId}/likes", cafe1.getId()); + + //then + assertThat(response.statusCode()).isEqualTo(OK.value()); + } + + @Test + @DisplayName("사용자의 좋아요 카페 목록의 카페들을 조회한다.") + void getLikedCafeDetails() { + //given + final Member member = new Member("1234", "도치", "도치.img"); + member.updateLikedCafesBy(cafe1, true); + member.updateLikedCafesBy(cafe2, true); + Member savedMember = memberRepository.save(member); + + //when + final Response response = customGivenWithDocs(likedCafeOfMemberDocument()) + .get("/members/{memberId}/liked-cafes/details", savedMember.getId()); + + //then + final List responses = response.jsonPath().getList(".", LikedCafeResponse.class); + + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(responses).extracting("id") + .containsExactly(cafe2.getId(), cafe1.getId()); + }); + } + + @Test + @DisplayName("사용자의 빈 좋아요 카페 목록의 카페들을 조회한다.") + void getLikedCafeDetailsWhenEmpty() { + //given + final Member savedMember = memberRepository.save(new Member("1234", "도치", "도치.img")); + + //when + final Response response = customGiven() + .get("/members/{memberId}/liked-cafes/details", savedMember.getId()); + + //then + assertThat(response.jsonPath().getList("")).isEmpty(); + } +} From b7a9e0d8b8c6b9256283979220e37be5c676bf08 Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 18:03:37 +0900 Subject: [PATCH 07/10] =?UTF-8?q?test:=20LocationControllerTest=20customGi?= =?UTF-8?q?ven=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/CafeAdminControllerTest.java | 3 +- .../LocationControllerTest.java | 78 ++++++++----------- .../location/LocationDocuments.java | 29 +++++++ 3 files changed, 63 insertions(+), 47 deletions(-) rename server/src/test/java/com/project/yozmcafe/controller/{ => location}/LocationControllerTest.java (69%) create mode 100644 server/src/test/java/com/project/yozmcafe/controller/location/LocationDocuments.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java index 68f9113c..95a277df 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java @@ -109,10 +109,11 @@ void findAll() { saveCafe(); saveCafe(); - //when, then + //when final Response response = customGivenWithDocs(adminAllCafesFindDocument()) .get("/admin/cafes"); + //then assertThat(response.statusCode()).isEqualTo(OK.value()); } diff --git a/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/location/LocationControllerTest.java similarity index 69% rename from server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java rename to server/src/test/java/com/project/yozmcafe/controller/location/LocationControllerTest.java index b6366b3d..73785196 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/LocationControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/location/LocationControllerTest.java @@ -1,16 +1,12 @@ -package com.project.yozmcafe.controller; +package com.project.yozmcafe.controller.location; -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static com.project.yozmcafe.controller.location.LocationDocuments.findCafesInMapDocument; import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import java.io.File; import java.time.LocalTime; @@ -21,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import com.fasterxml.jackson.databind.ObjectMapper; +import com.project.yozmcafe.controller.BaseControllerTest; import com.project.yozmcafe.controller.dto.cafe.AvailableTimeRequest; import com.project.yozmcafe.controller.dto.cafe.CafeCoordinateRequest; import com.project.yozmcafe.controller.dto.cafe.CafeLocationResponse; @@ -38,13 +35,30 @@ class LocationControllerTest extends BaseControllerTest { @Autowired CafeRepository cafeRepository; - private File image = new File("src/test/resources/image.png"); - @Test @DisplayName("입력받은 좌표와 델타 좌표로 범위내에 있는 모든 카페를 반환한다.") void findCafesFromLocation() { //given doNothing().when(s3Client).upload(any()); + saveCafesAndCoordinates(); + + //when + final Response response = customGivenWithDocs(findCafesInMapDocument()) + .queryParam("latitude", 20) + .queryParam("longitude", 10) + .queryParam("latitudeDelta", 0.004504504505) + .queryParam("longitudeDelta", 1) + .get("/cafes/location"); + + //then + final List results = response.jsonPath().getList(".", CafeLocationResponse.class); + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(200); + assertThat(results).hasSize(6); + }); + } + + private void saveCafesAndCoordinates() { final String cafeId1 = saveCafe("폴로카페", "영도"); final String cafeId2 = saveCafe("솔스카페", "기장"); final String cafeId3 = saveCafe("오션카페", "인천"); @@ -59,48 +73,12 @@ void findCafesFromLocation() { saveLocation(cafeId5, 20.005, 10); saveLocation(cafeId6, 20.006, 10); saveLocation(cafeId7, 30.007, 10); - - //when - final Response response = given(spec) - .log().all() - .filter(document("Location/지도 범위 내 모든 카페 조회", - queryParameters( - parameterWithName("latitude").description("기준 위도"), - parameterWithName("longitude").description("기준 경도"), - parameterWithName("latitudeDelta").description("기준 위도로부터 지도 내 최고 위도까지의 차"), - parameterWithName("longitudeDelta").description("기준 경도로부터 지도 내 최고 경도까지의 차") - ), - responseFields( - fieldWithPath("[].id").description("카페 Id"), - fieldWithPath("[].name").description("카페 이름"), - fieldWithPath("[].address").description("카페 주소"), - fieldWithPath("[].latitude").description("카페의 위도"), - fieldWithPath("[].longitude").description("카페의 경도") - ))) - .when() - .get("/cafes/location?latitude=20&longitude=10&latitudeDelta=0.004504504505&longitudeDelta=1"); - - final List results = response.then().log().all() - .extract().jsonPath().getList(".", CafeLocationResponse.class); - - //then - assertSoftly(softAssertions -> { - assertThat(response.statusCode()).isEqualTo(200); - assertThat(results).hasSize(6); - }); - } - - private void saveLocation(final String cafeId, final double latitude, final double longitude) { - given() - .contentType(JSON) - .body(new CafeCoordinateRequest(latitude, longitude)) - .when() - .post("/admin/cafes/{cafeId}/coordinate", cafeId); } private String saveCafe(final String name, final String address) { + final File image = new File("src/test/resources/image.png"); final String cafeRequest = makeCafeRequest(name, address); - final String location = given().log().all() + final String location = customGiven() .contentType("multipart/form-data;charset=UTF-8") .multiPart("request", cafeRequest, "application/json") .multiPart("images", image, "image/png") @@ -141,4 +119,12 @@ private DetailRequest detail() { return new DetailRequest(List.of(time1, time2, time3, time4, time5, time6, time7), "지도 url", "존맛탱구리", "01032472601"); } + + private void saveLocation(final String cafeId, final double latitude, final double longitude) { + given() + .contentType(JSON) + .body(new CafeCoordinateRequest(latitude, longitude)) + .when() + .post("/admin/cafes/{cafeId}/coordinate", cafeId); + } } diff --git a/server/src/test/java/com/project/yozmcafe/controller/location/LocationDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/location/LocationDocuments.java new file mode 100644 index 00000000..d9e9384c --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/location/LocationDocuments.java @@ -0,0 +1,29 @@ +package com.project.yozmcafe.controller.location; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class LocationDocuments { + + public static RestDocumentationFilter findCafesInMapDocument() { + return document("Location/지도 범위 내 모든 카페 조회", + queryParameters( + parameterWithName("latitude").description("기준 위도"), + parameterWithName("longitude").description("기준 경도"), + parameterWithName("latitudeDelta").description("기준 위도로부터 지도 내 최고 위도까지의 차"), + parameterWithName("longitudeDelta").description("기준 경도로부터 지도 내 최고 경도까지의 차") + ), + responseFields( + fieldWithPath("[].id").description("카페 Id"), + fieldWithPath("[].name").description("카페 이름"), + fieldWithPath("[].address").description("카페 주소"), + fieldWithPath("[].latitude").description("카페의 위도"), + fieldWithPath("[].longitude").description("카페의 경도") + )); + } +} From ad4bc903ade066c45a4285c27827c691cf5c517d Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 18:11:59 +0900 Subject: [PATCH 08/10] =?UTF-8?q?test:=20MemberControllerTest=20customGive?= =?UTF-8?q?n=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberControllerTest.java | 49 ------------------- .../member/MemberControllerTest.java | 39 +++++++++++++++ .../controller/member/MemberDocuments.java | 24 +++++++++ 3 files changed, 63 insertions(+), 49 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/MemberControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/member/MemberControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/member/MemberDocuments.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/MemberControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/MemberControllerTest.java deleted file mode 100644 index cce9ab9b..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/MemberControllerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.project.yozmcafe.controller; - -import com.project.yozmcafe.controller.dto.MemberResponse; -import com.project.yozmcafe.domain.member.Member; -import com.project.yozmcafe.domain.member.MemberRepository; -import io.restassured.RestAssured; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; - -class MemberControllerTest extends BaseControllerTest { - - @Autowired - private MemberRepository memberRepository; - - @Test - @DisplayName("id로 멤버 조회") - void findById() { - //given - final Member member = memberRepository.save(new Member("12413", "연어", "image")); - final MemberResponse expected = MemberResponse.from(member); - - //when - final MemberResponse response = RestAssured.given(spec).log().all() - .filter(document("멤버 조회", - pathParameters( - parameterWithName("memberId").description("멤버 ID") - ), responseFields( - fieldWithPath("id").description("멤버 아이디"), - fieldWithPath("name").description("멤버 이름"), - fieldWithPath("imageUrl").description("멤버 사진") - ) - )) - .when() - .get("/members/{memberId}", member.getId()) - .then() - .extract().response().as(MemberResponse.class); - - //then - assertThat(response).isEqualTo(expected); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/member/MemberControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/member/MemberControllerTest.java new file mode 100644 index 00000000..0cfa1fca --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/member/MemberControllerTest.java @@ -0,0 +1,39 @@ +package com.project.yozmcafe.controller.member; + +import static com.project.yozmcafe.controller.member.MemberDocuments.findMemberDocument; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.springframework.http.HttpStatus.OK; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.domain.member.Member; +import com.project.yozmcafe.domain.member.MemberRepository; + +import io.restassured.response.Response; + +class MemberControllerTest extends BaseControllerTest { + + @Autowired + private MemberRepository memberRepository; + + @Test + @DisplayName("id로 멤버 조회") + void findById() { + //given + final Member member = memberRepository.save(new Member("12413", "연어", "image")); + + //when + final Response response = customGivenWithDocs(findMemberDocument()) + .get("/members/{memberId}", member.getId()); + + //then + assertSoftly(softAssertions -> { + assertThat(response.statusCode()).isEqualTo(OK.value()); + assertThat(response.jsonPath().getString("id")).isEqualTo(member.getId()); + }); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/member/MemberDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/member/MemberDocuments.java new file mode 100644 index 00000000..236e9ee1 --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/member/MemberDocuments.java @@ -0,0 +1,24 @@ +package com.project.yozmcafe.controller.member; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class MemberDocuments { + + public static RestDocumentationFilter findMemberDocument() { + return document("멤버 조회", + pathParameters( + parameterWithName("memberId").description("멤버 ID") + ), responseFields( + fieldWithPath("id").description("멤버 아이디"), + fieldWithPath("name").description("멤버 이름"), + fieldWithPath("imageUrl").description("멤버 사진") + ) + ); + } +} From 6e4ef906e45ef05353a27aa9dee919548f7bcd20 Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 18:19:00 +0900 Subject: [PATCH 09/10] =?UTF-8?q?test:=20MenuControllerTest=20customGiven?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MenuControllerTest.java | 72 ------------------- .../controller/menu/MenuControllerTest.java | 52 ++++++++++++++ .../controller/menu/MenuDocuments.java | 32 +++++++++ 3 files changed, 84 insertions(+), 72 deletions(-) delete mode 100644 server/src/test/java/com/project/yozmcafe/controller/MenuControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/menu/MenuControllerTest.java create mode 100644 server/src/test/java/com/project/yozmcafe/controller/menu/MenuDocuments.java diff --git a/server/src/test/java/com/project/yozmcafe/controller/MenuControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/MenuControllerTest.java deleted file mode 100644 index 771c8e56..00000000 --- a/server/src/test/java/com/project/yozmcafe/controller/MenuControllerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.project.yozmcafe.controller; - -import com.project.yozmcafe.domain.cafe.Cafe; -import com.project.yozmcafe.domain.cafe.CafeRepository; -import com.project.yozmcafe.domain.menu.Menu; -import com.project.yozmcafe.domain.menu.MenuBoard; -import com.project.yozmcafe.domain.menu.MenuBoardRepository; -import com.project.yozmcafe.domain.menu.MenuRepository; -import com.project.yozmcafe.fixture.Fixture; -import io.restassured.response.Response; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; - -class MenuControllerTest extends BaseControllerTest { - - @Autowired - private CafeRepository cafeRepository; - @Autowired - private MenuRepository menuRepository; - @Autowired - private MenuBoardRepository menuBoardRepository; - - @Test - @DisplayName("특정 카페의 메뉴와 메뉴판을 조회 한다.") - void getMenus() { - //given - final Cafe cafe = cafeRepository.save(Fixture.getCafe("오션카페", "선릉역", 1)); - final Menu savedMenu = menuRepository.save(new Menu(cafe, 1, "뜨거운 아이스 아메리카노", - "아메리카노.img", "뜨겁지만 차가워요", "5000", true)); - final MenuBoard savedMenuBoard = menuBoardRepository.save(new MenuBoard(cafe, 1, "메뉴판")); - - //when - final Response response = given(spec).log().all() - .filter(document("메뉴/메뉴 조회", - pathParameters( - parameterWithName("cafeId").description("카페 ID") - ), responseFields( - fieldWithPath("cafeId").description("카페 ID"), - fieldWithPath("menuBoards[].id").description("메뉴판 ID"), - fieldWithPath("menuBoards[].priority").description("메뉴판 우선순위"), - fieldWithPath("menuBoards[].imageUrl").description("메뉴판 이미지 url"), - fieldWithPath("menus[].id").description("메뉴 ID"), - fieldWithPath("menus[].priority").description("메뉴 우선순위"), - fieldWithPath("menus[].name").description("메뉴 이름"), - fieldWithPath("menus[].imageUrl").description("메뉴 이미지 url"), - fieldWithPath("menus[].description").description("메뉴 설명"), - fieldWithPath("menus[].price").description("메뉴 가격"), - fieldWithPath("menus[].isRecommended").description("대표 메뉴 여부") - ) - )) - .when() - .get("/cafes/{cafeId}/menus", cafe.getId()); - - //then - assertAll( - () -> assertThat(response.jsonPath().getString("menus[0].name")).isEqualTo(savedMenu.getName()), - () -> assertThat(response.jsonPath().getString("menus[0].imageUrl")).isEqualTo(savedMenu.getImageUrl()), - () -> assertThat(response.jsonPath().getString("menus[0].description")).isEqualTo(savedMenu.getDescription()), - () -> assertThat(response.jsonPath().getString("menuBoards[0].imageUrl")).isEqualTo(savedMenuBoard.getImageUrl()) - ); - } -} diff --git a/server/src/test/java/com/project/yozmcafe/controller/menu/MenuControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/menu/MenuControllerTest.java new file mode 100644 index 00000000..e72cb2bf --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/menu/MenuControllerTest.java @@ -0,0 +1,52 @@ +package com.project.yozmcafe.controller.menu; + +import static com.project.yozmcafe.controller.menu.MenuDocuments.menuAndMenuBoardDocument; +import static org.assertj.core.api.Assertions.assertThat; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.project.yozmcafe.controller.BaseControllerTest; +import com.project.yozmcafe.domain.cafe.Cafe; +import com.project.yozmcafe.domain.cafe.CafeRepository; +import com.project.yozmcafe.domain.menu.Menu; +import com.project.yozmcafe.domain.menu.MenuBoard; +import com.project.yozmcafe.domain.menu.MenuBoardRepository; +import com.project.yozmcafe.domain.menu.MenuRepository; +import com.project.yozmcafe.fixture.Fixture; + +import io.restassured.response.Response; + +class MenuControllerTest extends BaseControllerTest { + + @Autowired + private CafeRepository cafeRepository; + @Autowired + private MenuRepository menuRepository; + @Autowired + private MenuBoardRepository menuBoardRepository; + + @Test + @DisplayName("특정 카페의 메뉴와 메뉴판을 조회 한다.") + void getMenus() { + //given + final Cafe cafe = cafeRepository.save(Fixture.getCafe("오션카페", "선릉역", 1)); + final Menu savedMenu = menuRepository.save(new Menu(cafe, 1, "뜨거운 아이스 아메리카노", + "아메리카노.img", "뜨겁지만 차가워요", "5000", true)); + final MenuBoard savedMenuBoard = menuBoardRepository.save(new MenuBoard(cafe, 1, "메뉴판")); + + //when + final Response response = customGivenWithDocs(menuAndMenuBoardDocument()) + .get("/cafes/{cafeId}/menus", cafe.getId()); + + //then + SoftAssertions.assertSoftly(softAssertions -> { + assertThat(response.jsonPath().getString("menus[0].name")).isEqualTo(savedMenu.getName()); + assertThat(response.jsonPath().getString("menus[0].imageUrl")).isEqualTo(savedMenu.getImageUrl()); + assertThat(response.jsonPath().getString("menus[0].description")).isEqualTo(savedMenu.getDescription()); + assertThat(response.jsonPath().getString("menuBoards[0].imageUrl")).isEqualTo(savedMenuBoard.getImageUrl()); + }); + } +} diff --git a/server/src/test/java/com/project/yozmcafe/controller/menu/MenuDocuments.java b/server/src/test/java/com/project/yozmcafe/controller/menu/MenuDocuments.java new file mode 100644 index 00000000..575097cb --- /dev/null +++ b/server/src/test/java/com/project/yozmcafe/controller/menu/MenuDocuments.java @@ -0,0 +1,32 @@ +package com.project.yozmcafe.controller.menu; + +import static com.epages.restdocs.apispec.RestAssuredRestDocumentationWrapper.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +import org.springframework.restdocs.restassured.RestDocumentationFilter; + +public class MenuDocuments { + + public static RestDocumentationFilter menuAndMenuBoardDocument() { + return document("메뉴/메뉴 조회", + pathParameters( + parameterWithName("cafeId").description("카페 ID") + ), responseFields( + fieldWithPath("cafeId").description("카페 ID"), + fieldWithPath("menuBoards[].id").description("메뉴판 ID"), + fieldWithPath("menuBoards[].priority").description("메뉴판 우선순위"), + fieldWithPath("menuBoards[].imageUrl").description("메뉴판 이미지 url"), + fieldWithPath("menus[].id").description("메뉴 ID"), + fieldWithPath("menus[].priority").description("메뉴 우선순위"), + fieldWithPath("menus[].name").description("메뉴 이름"), + fieldWithPath("menus[].imageUrl").description("메뉴 이미지 url"), + fieldWithPath("menus[].description").description("메뉴 설명"), + fieldWithPath("menus[].price").description("메뉴 가격"), + fieldWithPath("menus[].isRecommended").description("대표 메뉴 여부") + ) + ); + } +} From 0305396861cef94e0216c6eb818634614bdfe8db Mon Sep 17 00:00:00 2001 From: dev_kong Date: Thu, 5 Oct 2023 18:41:44 +0900 Subject: [PATCH 10/10] =?UTF-8?q?test:=20OAuthClient=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=95=84=EB=93=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yozmcafe/controller/admin/CafeAdminControllerTest.java | 1 + .../java/com/project/yozmcafe/service/BaseServiceTest.java | 3 --- .../com/project/yozmcafe/service/auth/AuthServiceTest.java | 3 +++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java index 95a277df..72f80e33 100644 --- a/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java +++ b/server/src/test/java/com/project/yozmcafe/controller/admin/CafeAdminControllerTest.java @@ -139,6 +139,7 @@ void saveCoordinate() { //when final Response response = customGivenWithDocs(adminLocationSaveDocument()) + .contentType(JSON) .body(new CafeCoordinateRequest(20, 10)) .post("/admin/cafes/{cafeId}/coordinate", location); diff --git a/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java index 759e9556..98bbe7fc 100644 --- a/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/BaseServiceTest.java @@ -5,11 +5,8 @@ import com.project.yozmcafe.BaseTest; import com.project.yozmcafe.domain.S3Client; -import com.project.yozmcafe.service.auth.GoogleOAuthClient; public abstract class BaseServiceTest extends BaseTest { - @SpyBean - protected GoogleOAuthClient googleOAuthClient; @SpyBean protected S3Client s3Client; } diff --git a/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java b/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java index fea32167..740ef784 100644 --- a/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java +++ b/server/src/test/java/com/project/yozmcafe/service/auth/AuthServiceTest.java @@ -9,6 +9,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.transaction.annotation.Transactional; import com.project.yozmcafe.controller.auth.OAuthProvider; @@ -31,6 +32,8 @@ class AuthServiceTest extends BaseServiceTest { private CafeRepository cafeRepository; @Autowired private AuthService authService; + @SpyBean + protected GoogleOAuthClient googleOAuthClient; @Test @DisplayName("회원가입된 상태의 유저로 createAccessToken 호출하면 멤버를 새로 저장하지 않는다")