diff --git a/src/main/java/today/seasoning/seasoning/friendship/controller/FriendshipController.java b/src/main/java/today/seasoning/seasoning/friendship/controller/FriendshipController.java index 9d65012..d877248 100644 --- a/src/main/java/today/seasoning/seasoning/friendship/controller/FriendshipController.java +++ b/src/main/java/today/seasoning/seasoning/friendship/controller/FriendshipController.java @@ -14,13 +14,13 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import today.seasoning.seasoning.common.UserPrincipal; -import today.seasoning.seasoning.friendship.dto.FindUserFriendsResult; +import today.seasoning.seasoning.friendship.dto.FindUserFriendsResponse; import today.seasoning.seasoning.friendship.dto.SearchUserResult; import today.seasoning.seasoning.friendship.dto.UserIdDto; import today.seasoning.seasoning.friendship.service.AcceptFriendRequestService; import today.seasoning.seasoning.friendship.service.CancelFriendRequestService; import today.seasoning.seasoning.friendship.service.DeclineFriendRequestService; -import today.seasoning.seasoning.friendship.service.FindUserFriendsService; +import today.seasoning.seasoning.friendship.service.FindAllFriendsService; import today.seasoning.seasoning.friendship.service.SearchUserService; import today.seasoning.seasoning.friendship.service.SendFriendRequestService; import today.seasoning.seasoning.friendship.service.UnfriendService; @@ -32,7 +32,7 @@ public class FriendshipController { private final UnfriendService unfriendService; private final SearchUserService searchUserService; - private final FindUserFriendsService findUserFriendsService; + private final FindAllFriendsService findAllFriendsService; private final SendFriendRequestService sendFriendRequestService; private final AcceptFriendRequestService acceptFriendRequestService; private final CancelFriendRequestService cancelFriendRequestService; @@ -52,10 +52,10 @@ public ResponseEntity requestFriendship( } @GetMapping("/list") - public ResponseEntity> findUserFriends(@AuthenticationPrincipal UserPrincipal principal) { + public ResponseEntity> findUserFriends(@AuthenticationPrincipal UserPrincipal principal) { Long userId = principal.getId(); - List findUserFriendResults = findUserFriendsService.doFind(userId); - return ResponseEntity.ok().body(findUserFriendResults); + List response = findAllFriendsService.doService(userId); + return ResponseEntity.ok().body(response); } @PutMapping("/add/accept") diff --git a/src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResult.java b/src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResponse.java similarity index 79% rename from src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResult.java rename to src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResponse.java index 1bcfba2..09ff214 100644 --- a/src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResult.java +++ b/src/main/java/today/seasoning/seasoning/friendship/dto/FindUserFriendsResponse.java @@ -7,15 +7,15 @@ @Getter @RequiredArgsConstructor -public class FindUserFriendsResult { +public class FindUserFriendsResponse { private final String id; private final String nickname; private final String accountId; private final String profileImageUrl; - public static FindUserFriendsResult build(User friend) { - return new FindUserFriendsResult( + public static FindUserFriendsResponse build(User friend) { + return new FindUserFriendsResponse( TsidUtil.toString(friend.getId()), friend.getNickname(), friend.getAccountId(), diff --git a/src/main/java/today/seasoning/seasoning/friendship/service/FindUserFriendsService.java b/src/main/java/today/seasoning/seasoning/friendship/service/FindAllFriendsService.java similarity index 81% rename from src/main/java/today/seasoning/seasoning/friendship/service/FindUserFriendsService.java rename to src/main/java/today/seasoning/seasoning/friendship/service/FindAllFriendsService.java index 9f988b5..afdd342 100644 --- a/src/main/java/today/seasoning/seasoning/friendship/service/FindUserFriendsService.java +++ b/src/main/java/today/seasoning/seasoning/friendship/service/FindAllFriendsService.java @@ -7,20 +7,20 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import today.seasoning.seasoning.friendship.domain.FriendshipRepository; -import today.seasoning.seasoning.friendship.dto.FindUserFriendsResult; +import today.seasoning.seasoning.friendship.dto.FindUserFriendsResponse; @Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class FindUserFriendsService { +public class FindAllFriendsService { private final FriendshipRepository friendshipRepository; - public List doFind(Long userId) { + public List doService(Long userId) { return friendshipRepository.findFriendsByUserId(userId) .stream() - .map(FindUserFriendsResult::build) + .map(FindUserFriendsResponse::build) .collect(Collectors.toList()); } } diff --git a/src/test/java/today/seasoning/seasoning/BaseIntegrationTest.java b/src/test/java/today/seasoning/seasoning/BaseIntegrationTest.java index e60b9c6..aca777b 100644 --- a/src/test/java/today/seasoning/seasoning/BaseIntegrationTest.java +++ b/src/test/java/today/seasoning/seasoning/BaseIntegrationTest.java @@ -8,6 +8,8 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; @@ -33,41 +35,57 @@ public class BaseIntegrationTest { } @Autowired - JdbcTemplate jdbcTemplate; + private JdbcTemplate jdbcTemplate; @LocalServerPort - int port; + private int port; @BeforeEach - void setPort() { + void init() { // 실제 서블릿 컨테이너 실행을 위한 RANDOM PORT 설정 RestAssured.port = port; // 모든 테이블 데이터 초기화 (정적 데이터 fortune, solar_term 제외) Resource resource = new ClassPathResource("/data/clear.sql"); try { - String sql = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)); + String sql = FileCopyUtils.copyToString( + new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)); Arrays.stream(sql.split("\n")).forEach(jdbcTemplate::execute); } catch (IOException e) { throw new RuntimeException("Error reading or executing SQL script: /data/clear.sql", e); } } - public ExtractableResponse post(String uri, Long userId, JSONObject jsonBody) { - String accessToken = JwtUtil.createToken(userId).getAccessToken(); - + protected ExtractableResponse post(String url, Long userId, JSONObject jsonBody) { RequestSpecification request = RestAssured .given().log().all() .contentType("application/json") - .header("Authorization", "Bearer " + accessToken); + .header("Authorization", "Bearer " + createAccessToken(userId)); if (jsonBody != null) { request.body(jsonBody.toString()); } return request - .when().post(uri) + .when().post(url) .then().log().all().extract(); } + protected ExtractableResponse get(String url, Long userId) { + return get(url, userId, new HashMap<>()); + } + + + protected ExtractableResponse get(String url, Long userId, Map params) { + return RestAssured + .given().log().all() + .header("Authorization", "Bearer " + createAccessToken(userId)) + .params(params) + .when().get(url) + .then().log().all().extract(); + } + + protected String createAccessToken(Long userId) { + return JwtUtil.createToken(userId).getAccessToken(); + } } diff --git a/src/test/java/today/seasoning/seasoning/friendship/integration/FindAllFriendsIntegrationTest.java b/src/test/java/today/seasoning/seasoning/friendship/integration/FindAllFriendsIntegrationTest.java new file mode 100644 index 0000000..90733f8 --- /dev/null +++ b/src/test/java/today/seasoning/seasoning/friendship/integration/FindAllFriendsIntegrationTest.java @@ -0,0 +1,141 @@ +package today.seasoning.seasoning.friendship.integration; + +import io.restassured.common.mapper.TypeRef; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import java.util.List; +import java.util.stream.Collectors; +import org.assertj.core.api.SoftAssertions; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +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 today.seasoning.seasoning.BaseIntegrationTest; +import today.seasoning.seasoning.common.enums.LoginType; +import today.seasoning.seasoning.common.util.TsidUtil; +import today.seasoning.seasoning.friendship.domain.Friendship; +import today.seasoning.seasoning.friendship.domain.FriendshipRepository; +import today.seasoning.seasoning.friendship.dto.FindUserFriendsResponse; +import today.seasoning.seasoning.user.domain.User; +import today.seasoning.seasoning.user.domain.UserRepository; + +@DisplayName("친구 목록 조회 통합 테스트") +public class FindAllFriendsIntegrationTest extends BaseIntegrationTest { + + @Autowired + UserRepository userRepository; + + @Autowired + FriendshipRepository friendshipRepository; + + @InjectSoftAssertions + SoftAssertions softAssertions; + + // API 주소 + static String url = "/friend/list"; + + // Mock 유저 정보 + List users; + + @BeforeEach + void initMockUsers() { + //given + users = List.of( + new User("userNickname0", "https://test.org/user0.jpg", "user0@email.com", LoginType.KAKAO), + new User("userNickname1", "https://test.org/user1.jpg", "user1@email.com", LoginType.KAKAO), + new User("userNickname2", "https://test.org/user2.jpg", "user2@email.com", LoginType.KAKAO), + new User("userNickname3", "https://test.org/user3.jpg", "user3@email.com", LoginType.KAKAO) + ); + userRepository.saveAll(users); + } + + @Test + @DisplayName("모든 친구가 조회되어야 한다") + void findAllFriends() { + //given : 회원이 user1, user2, user3와 친구일 때 + User user = users.get(0); + List friends = users.subList(1, 4); + + setFriendships(user, friends); + + //when : 친구 목록을 조회하면 + ExtractableResponse response = get(url, user.getId()); + + List responseFriendList = response.body().as(new TypeRef<>() { + }); + + //then : 응답은 다음과 같아야 한다 + softAssertions.assertThat(response.statusCode()) + .as("상태 코드는 200이어야 한다") + .isEqualTo(200); + + softAssertions.assertThat(responseFriendList.size()) + .as("조회된 친구의 수는 3명이다.") + .isEqualTo(3); + + softAssertions.assertThat(responseFriendList) + .as("조회된 친구의 정보는 실제 회원의 정보와 일치해야 한다") + .usingRecursiveComparison() + .isEqualTo(createFindUserFriendsResponse(friends)); + } + + @Test + @DisplayName("친구가 아닌 회원은 조회되면 안된다") + void findAllFriendsExcludingNonFriends() { + //given : 회원이 user1과 user2와 친구이고, user3와는 친구가 아닐 때 + User user = users.get(0); + List friends = users.subList(1, 3); + User nonFriendUser = users.get(3); + + setFriendships(user, friends); + + //when : 친구 목록을 조회하면 + ExtractableResponse response = get(url, user.getId()); + + List responseFriendList = response.body().as(new TypeRef<>() { + }); + + //then : 응답은 다음과 같아야 한다 + softAssertions.assertThat(response.statusCode()) + .as("상태 코드는 200이어야 한다") + .isEqualTo(200); + + softAssertions.assertThat(responseFriendList.size()) + .as("조회된 친구의 수는 2명이다.") + .isEqualTo(2); + + softAssertions.assertThat(responseFriendList) + .as("조회된 친구의 정보는 실제 회원의 정보와 일치해야 한다") + .usingRecursiveComparison() + .isEqualTo(createFindUserFriendsResponse(friends)); + + softAssertions.assertThat(responseFriendList) + .as("친구가 아닌 회원의 정보는 조회되면 안된다") + .usingRecursiveComparison() + .isNotEqualTo(createFindUserFriendsResponse(nonFriendUser)); + } + + + private void setFriendships(User user, List friends) { + friends.forEach(friend -> { + friendshipRepository.save(new Friendship(user, friend)); + friendshipRepository.save(new Friendship(friend, user)); + }); + } + + private List createFindUserFriendsResponse(List users) { + return users.stream() + .map(this::createFindUserFriendsResponse) + .collect(Collectors.toList()); + } + + private FindUserFriendsResponse createFindUserFriendsResponse(User user) { + return new FindUserFriendsResponse( + TsidUtil.toString(user.getId()), + user.getNickname(), + user.getAccountId(), + user.getProfileImageUrl()); + } + +} diff --git a/src/test/java/today/seasoning/seasoning/friendship/service/FindUserFriendsServiceTest.java b/src/test/java/today/seasoning/seasoning/friendship/service/FindAllFriendsServiceTest.java similarity index 70% rename from src/test/java/today/seasoning/seasoning/friendship/service/FindUserFriendsServiceTest.java rename to src/test/java/today/seasoning/seasoning/friendship/service/FindAllFriendsServiceTest.java index a79280c..4128260 100644 --- a/src/test/java/today/seasoning/seasoning/friendship/service/FindUserFriendsServiceTest.java +++ b/src/test/java/today/seasoning/seasoning/friendship/service/FindAllFriendsServiceTest.java @@ -12,17 +12,17 @@ import today.seasoning.seasoning.common.enums.LoginType; import today.seasoning.seasoning.common.util.TsidUtil; import today.seasoning.seasoning.friendship.domain.FriendshipRepository; -import today.seasoning.seasoning.friendship.dto.FindUserFriendsResult; +import today.seasoning.seasoning.friendship.dto.FindUserFriendsResponse; import today.seasoning.seasoning.user.domain.User; @DisplayName("친구 목록 조회 서비스") @ExtendWith(MockitoExtension.class) -class FindUserFriendsServiceTest { +class FindAllFriendsServiceTest { @Mock FriendshipRepository friendshipRepository; @InjectMocks - FindUserFriendsService findUserFriendsService; + FindAllFriendsService findAllFriendsService; @Test @DisplayName("성공") @@ -33,17 +33,17 @@ void success() { User friend2 = new User("friend2", "https://test/friend2.jpg", "friend2@email.com", LoginType.KAKAO); User friend3 = new User("friend3", "https://test/friend3.jpg", "friend3@email.com", LoginType.KAKAO); - List expectedResult = List.of( - new FindUserFriendsResult(TsidUtil.toString(friend1.getId()), friend1.getNickname(), friend1.getAccountId(), friend1.getProfileImageUrl()), - new FindUserFriendsResult(TsidUtil.toString(friend2.getId()), friend2.getNickname(), friend2.getAccountId(), friend2.getProfileImageUrl()), - new FindUserFriendsResult(TsidUtil.toString(friend3.getId()), friend3.getNickname(), friend3.getAccountId(), friend3.getProfileImageUrl()) + List expectedResult = List.of( + new FindUserFriendsResponse(TsidUtil.toString(friend1.getId()), friend1.getNickname(), friend1.getAccountId(), friend1.getProfileImageUrl()), + new FindUserFriendsResponse(TsidUtil.toString(friend2.getId()), friend2.getNickname(), friend2.getAccountId(), friend2.getProfileImageUrl()), + new FindUserFriendsResponse(TsidUtil.toString(friend3.getId()), friend3.getNickname(), friend3.getAccountId(), friend3.getProfileImageUrl()) ); BDDMockito.given(friendshipRepository.findFriendsByUserId(user.getId())) .willReturn(List.of(friend1, friend2, friend3)); //when - List actualResult = findUserFriendsService.doFind(user.getId()); + List actualResult = findAllFriendsService.doService(user.getId()); //then Assertions.assertThat(actualResult)