Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

통합 테스트 작성 : 친구 목록 조회 #61

Merged
merged 5 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -52,10 +52,10 @@ public ResponseEntity<String> requestFriendship(
}

@GetMapping("/list")
public ResponseEntity<List<FindUserFriendsResult>> findUserFriends(@AuthenticationPrincipal UserPrincipal principal) {
public ResponseEntity<List<FindUserFriendsResponse>> findUserFriends(@AuthenticationPrincipal UserPrincipal principal) {
Long userId = principal.getId();
List<FindUserFriendsResult> findUserFriendResults = findUserFriendsService.doFind(userId);
return ResponseEntity.ok().body(findUserFriendResults);
List<FindUserFriendsResponse> response = findAllFriendsService.doService(userId);
return ResponseEntity.ok().body(response);
}

@PutMapping("/add/accept")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<FindUserFriendsResult> doFind(Long userId) {
public List<FindUserFriendsResponse> doService(Long userId) {
return friendshipRepository.findFriendsByUserId(userId)
.stream()
.map(FindUserFriendsResult::build)
.map(FindUserFriendsResponse::build)
.collect(Collectors.toList());
}
}
36 changes: 27 additions & 9 deletions src/test/java/today/seasoning/seasoning/BaseIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Response> post(String uri, Long userId, JSONObject jsonBody) {
String accessToken = JwtUtil.createToken(userId).getAccessToken();

protected ExtractableResponse<Response> 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<Response> get(String url, Long userId) {
return get(url, userId, new HashMap<>());
}


protected ExtractableResponse<Response> get(String url, Long userId, Map<String, Object> 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();
}
}
Original file line number Diff line number Diff line change
@@ -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<User> users;

@BeforeEach
void initMockUsers() {
//given
users = List.of(
new User("userNickname0", "https://test.org/user0.jpg", "[email protected]", LoginType.KAKAO),
new User("userNickname1", "https://test.org/user1.jpg", "[email protected]", LoginType.KAKAO),
new User("userNickname2", "https://test.org/user2.jpg", "[email protected]", LoginType.KAKAO),
new User("userNickname3", "https://test.org/user3.jpg", "[email protected]", LoginType.KAKAO)
);
userRepository.saveAll(users);
}

@Test
@DisplayName("모든 친구가 조회되어야 한다")
void findAllFriends() {
//given : 회원이 user1, user2, user3와 친구일 때
User user = users.get(0);
List<User> friends = users.subList(1, 4);

setFriendships(user, friends);

//when : 친구 목록을 조회하면
ExtractableResponse<Response> response = get(url, user.getId());

List<FindUserFriendsResponse> 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<User> friends = users.subList(1, 3);
User nonFriendUser = users.get(3);

setFriendships(user, friends);

//when : 친구 목록을 조회하면
ExtractableResponse<Response> response = get(url, user.getId());

List<FindUserFriendsResponse> 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<User> friends) {
friends.forEach(friend -> {
friendshipRepository.save(new Friendship(user, friend));
friendshipRepository.save(new Friendship(friend, user));
});
}

private List<FindUserFriendsResponse> createFindUserFriendsResponse(List<User> 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());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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("성공")
Expand All @@ -33,17 +33,17 @@ void success() {
User friend2 = new User("friend2", "https://test/friend2.jpg", "[email protected]", LoginType.KAKAO);
User friend3 = new User("friend3", "https://test/friend3.jpg", "[email protected]", LoginType.KAKAO);

List<FindUserFriendsResult> 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<FindUserFriendsResponse> 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<FindUserFriendsResult> actualResult = findUserFriendsService.doFind(user.getId());
List<FindUserFriendsResponse> actualResult = findAllFriendsService.doService(user.getId());

//then
Assertions.assertThat(actualResult)
Expand Down