diff --git a/src/main/java/daybyquest/badge/domain/Badges.java b/src/main/java/daybyquest/badge/domain/Badges.java index 9487a35..df0699a 100644 --- a/src/main/java/daybyquest/badge/domain/Badges.java +++ b/src/main/java/daybyquest/badge/domain/Badges.java @@ -12,8 +12,8 @@ public class Badges { this.badgeRepository = badgeRepository; } - public void save(final Badge badge) { - badgeRepository.save(badge); + public Badge save(final Badge badge) { + return badgeRepository.save(badge); } public void validateExistentById(final Long id) { diff --git a/src/main/java/daybyquest/group/application/SaveGroupService.java b/src/main/java/daybyquest/group/application/SaveGroupService.java index 2efc215..b1044bd 100644 --- a/src/main/java/daybyquest/group/application/SaveGroupService.java +++ b/src/main/java/daybyquest/group/application/SaveGroupService.java @@ -27,7 +27,7 @@ public SaveGroupService(final Groups groups, final ImageService imageService) { public Long invoke(final Long loginId, final SaveGroupRequest request, final MultipartFile file) { final Image image = imageService.convertToImage(CATEGORY, file); final Group group = toEntity(request, image); - return groups.save(loginId, group); + return groups.save(loginId, group).getId(); } public Group toEntity(final SaveGroupRequest request, final Image image) { diff --git a/src/main/java/daybyquest/group/domain/Groups.java b/src/main/java/daybyquest/group/domain/Groups.java index edf3260..46d9708 100644 --- a/src/main/java/daybyquest/group/domain/Groups.java +++ b/src/main/java/daybyquest/group/domain/Groups.java @@ -22,12 +22,12 @@ public class Groups { this.interests = interests; } - public Long save(final Long userId, final Group group) { + public Group save(final Long userId, final Group group) { interests.validateInterest(group.getInterest()); validateNotExistentByName(group.getName()); final Group savedGroup = groupRepository.save(group); groupUsers.addUser(GroupUser.createGroupManager(userId, savedGroup)); - return savedGroup.getId(); + return savedGroup; } public void validateNotExistentByName(final String name) { diff --git a/src/main/java/daybyquest/post/application/CheckPostService.java b/src/main/java/daybyquest/post/application/CheckPostService.java index ef1b0b4..410417b 100644 --- a/src/main/java/daybyquest/post/application/CheckPostService.java +++ b/src/main/java/daybyquest/post/application/CheckPostService.java @@ -14,7 +14,6 @@ @Service public class CheckPostService { - private final Quests quests; private final GroupUsers groupUsers; diff --git a/src/main/java/daybyquest/post/application/GetPostService.java b/src/main/java/daybyquest/post/application/GetPostService.java index 8e427d5..686fa63 100644 --- a/src/main/java/daybyquest/post/application/GetPostService.java +++ b/src/main/java/daybyquest/post/application/GetPostService.java @@ -3,7 +3,6 @@ import daybyquest.post.dto.response.PostWithQuestResponse; import daybyquest.post.query.PostDao; import daybyquest.post.query.PostData; -import daybyquest.quest.domain.Quests; import daybyquest.user.query.Profile; import daybyquest.user.query.ProfileDao; import org.springframework.stereotype.Service; @@ -16,12 +15,9 @@ public class GetPostService { private final ProfileDao profileDao; - private final Quests quests; - - public GetPostService(final PostDao postDao, final ProfileDao profileDao, final Quests quests) { + public GetPostService(final PostDao postDao, final ProfileDao profileDao) { this.postDao = postDao; this.profileDao = profileDao; - this.quests = quests; } @Transactional(readOnly = true) diff --git a/src/main/java/daybyquest/post/domain/Post.java b/src/main/java/daybyquest/post/domain/Post.java index 198ed9e..c8fdf11 100644 --- a/src/main/java/daybyquest/post/domain/Post.java +++ b/src/main/java/daybyquest/post/domain/Post.java @@ -136,4 +136,9 @@ private void validateQuestLink() { throw new InvalidDomainException(NOT_LINKED_POST); } } + + public Long getQuestId() { + validateQuestLink(); + return questId; + } } diff --git a/src/main/java/daybyquest/post/domain/Posts.java b/src/main/java/daybyquest/post/domain/Posts.java index cb779be..aa7e822 100644 --- a/src/main/java/daybyquest/post/domain/Posts.java +++ b/src/main/java/daybyquest/post/domain/Posts.java @@ -25,7 +25,7 @@ public class Posts { public Post save(final Post post) { users.validateExistentById(post.getUserId()); - if (post.getQuestId() != null) { + if (post.isQuestLinked()) { participants.validateExistent(post.getUserId(), post.getQuestId()); } return postRepository.save(post); diff --git a/src/main/java/daybyquest/quest/application/SaveQuestService.java b/src/main/java/daybyquest/quest/application/SaveQuestService.java index 5c8f0dd..25ea5f8 100644 --- a/src/main/java/daybyquest/quest/application/SaveQuestService.java +++ b/src/main/java/daybyquest/quest/application/SaveQuestService.java @@ -36,7 +36,7 @@ public SaveQuestService(final Quests quests, final Badges badges, final ImageSer @Transactional public Long invoke(final SaveQuestRequest request, final List files) { final Quest quest = toEntity(request, toImageList(files)); - final Long questId = quests.save(quest); + final Long questId = quests.save(quest).getId(); questClient.requestLabels(questId, quest.getImages().stream().map(Image::getIdentifier).toList(), quest.getImageDescription()); return questId; diff --git a/src/main/java/daybyquest/quest/application/group/SaveGroupQuestService.java b/src/main/java/daybyquest/quest/application/group/SaveGroupQuestService.java index 4b57b97..a4c1987 100644 --- a/src/main/java/daybyquest/quest/application/group/SaveGroupQuestService.java +++ b/src/main/java/daybyquest/quest/application/group/SaveGroupQuestService.java @@ -43,7 +43,7 @@ public Long invoke(final Long loginId, final SaveGroupQuestRequest request, final List files) { groupUsers.validateGroupManager(loginId, request.getGroupId()); final Quest quest = toEntity(request, toImageList(files)); - final Long questId = quests.save(quest); + final Long questId = quests.save(quest).getId(); questClient.requestLabels(questId, quest.getImages().stream().map(Image::getIdentifier).toList(), quest.getImageDescription()); return questId; diff --git a/src/main/java/daybyquest/quest/domain/Quests.java b/src/main/java/daybyquest/quest/domain/Quests.java index 9b23d00..f9951d1 100644 --- a/src/main/java/daybyquest/quest/domain/Quests.java +++ b/src/main/java/daybyquest/quest/domain/Quests.java @@ -27,13 +27,13 @@ public class Quests { this.badges = badges; } - public Long save(final Quest quest) { + public Quest save(final Quest quest) { if (quest.getBadgeId() != null) { badges.validateExistentById(quest.getBadgeId()); validateNotExistentByBadgeId(quest.getBadgeId()); } validateGroupQuest(quest); - return questRepository.save(quest).getId(); + return questRepository.save(quest); } private void validateGroupQuest(final Quest quest) { diff --git a/src/main/java/daybyquest/user/domain/User.java b/src/main/java/daybyquest/user/domain/User.java index a0032fe..78dcc11 100644 --- a/src/main/java/daybyquest/user/domain/User.java +++ b/src/main/java/daybyquest/user/domain/User.java @@ -19,6 +19,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; @@ -69,7 +70,7 @@ public class User { @Embedded private Image image; - @ElementCollection + @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "user_interest", joinColumns = @JoinColumn(name = "user_id")) @Column(length = 10) private List interests; diff --git a/src/test/java/daybyquest/group/domain/GroupsTest.java b/src/test/java/daybyquest/group/domain/GroupsTest.java index ef6f577..9aee0d5 100644 --- a/src/test/java/daybyquest/group/domain/GroupsTest.java +++ b/src/test/java/daybyquest/group/domain/GroupsTest.java @@ -42,7 +42,7 @@ public class GroupsTest { given(groupRepository.save(any(Group.class))).willReturn(GROUP_1.생성(groupId)); // when - final Long actualId = groups.save(userId, GROUP_1.생성()); + final Long actualId = groups.save(userId, GROUP_1.생성()).getId(); // then assertAll(() -> { diff --git a/src/test/java/daybyquest/post/application/CheckPostServiceTest.java b/src/test/java/daybyquest/post/application/CheckPostServiceTest.java new file mode 100644 index 0000000..7e273c2 --- /dev/null +++ b/src/test/java/daybyquest/post/application/CheckPostServiceTest.java @@ -0,0 +1,150 @@ +package daybyquest.post.application; + +import static daybyquest.global.error.ExceptionCode.ALREADY_JUDGED_POST; +import static daybyquest.global.error.ExceptionCode.NOT_GROUP_MANAGER; +import static daybyquest.global.error.ExceptionCode.NOT_LINKED_POST; +import static daybyquest.post.domain.PostState.FAIL; +import static daybyquest.post.domain.PostState.SUCCESS; +import static daybyquest.support.fixture.GroupFixtures.GROUP_1; +import static daybyquest.support.fixture.InterestFixtures.INTEREST; +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import daybyquest.global.error.exception.InvalidDomainException; +import daybyquest.group.domain.Group; +import daybyquest.group.domain.GroupUser; +import daybyquest.post.domain.Post; +import daybyquest.post.dto.request.CheckPostRequest; +import daybyquest.quest.domain.Quest; +import daybyquest.support.test.ServiceTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.util.ReflectionTestUtils; + +public class CheckPostServiceTest extends ServiceTest { + + @Autowired + private CheckPostService checkPostService; + + @Test + void 그룹장이_그룹_퀘스트를_성공_시킨다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Post post = POST_1.생성(aliceId, questId); + post.needCheck(); + final Long postId = posts.save(post).getId(); + + final CheckPostRequest request = 게시물_판정_요청(true); + + // when + checkPostService.invoke(aliceId, postId, request); + + // then + final Post actual = posts.getById(postId); + assertThat(actual.getState()).isEqualTo(SUCCESS); + } + + @Test + void 그룹장이_그룹_퀘스트를_실패_시킨다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Post post = POST_1.생성(aliceId, questId); + post.needCheck(); + final Long postId = posts.save(post).getId(); + + final CheckPostRequest request = 게시물_판정_요청(false); + + // when + checkPostService.invoke(aliceId, postId, request); + + // then + final Post actual = posts.getById(postId); + assertThat(actual.getState()).isEqualTo(FAIL); + } + + @Test + void 그룹장이_아니면_예외를_던진다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + final Long bobId = 중재자_권한으로_BOB을_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + groupUsers.addUser(GroupUser.createGroupMember(bobId, group)); + + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Post post = POST_1.생성(aliceId, questId); + post.needCheck(); + final Long postId = posts.save(post).getId(); + + final CheckPostRequest request = 게시물_판정_요청(false); + + // when & then + assertThatThrownBy(() -> checkPostService.invoke(bobId, postId, request)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(NOT_GROUP_MANAGER.getMessage()); + } + + @Test + void 퀘스트가_링크되지_않은_게시물을_확인할_수_없다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + + final Long postId = posts.save(POST_1.생성(aliceId)).getId(); + + final CheckPostRequest request = 게시물_판정_요청(true); + + // when & then + assertThatThrownBy(() -> checkPostService.invoke(aliceId, postId, request)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(NOT_LINKED_POST.getMessage()); + } + + @Test + void 이미_확인된_게시물은_확인할_수_없다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Post post = POST_1.생성(aliceId, questId); + post.success(); + final Long postId = posts.save(post).getId(); + + final CheckPostRequest request = 게시물_판정_요청(true); + + // when & then + assertThatThrownBy(() -> checkPostService.invoke(aliceId, postId, request)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(ALREADY_JUDGED_POST.getMessage()); + } + + private CheckPostRequest 게시물_판정_요청(final boolean approval) { + final CheckPostRequest request = new CheckPostRequest(); + ReflectionTestUtils.setField(request, "approval", approval); + return request; + } +} diff --git a/src/test/java/daybyquest/post/application/GetNeedCheckPostServiceTest.java b/src/test/java/daybyquest/post/application/GetNeedCheckPostServiceTest.java new file mode 100644 index 0000000..549c203 --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetNeedCheckPostServiceTest.java @@ -0,0 +1,78 @@ +package daybyquest.post.application; + +import static daybyquest.global.error.ExceptionCode.NOT_GROUP_MANAGER; +import static daybyquest.support.fixture.GroupFixtures.GROUP_1; +import static daybyquest.support.fixture.InterestFixtures.INTEREST; +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import daybyquest.global.error.exception.InvalidDomainException; +import daybyquest.group.domain.Group; +import daybyquest.group.domain.GroupUser; +import daybyquest.post.domain.Post; +import daybyquest.post.dto.response.SimplePostResponse; +import daybyquest.quest.domain.Quest; +import daybyquest.support.test.ServiceTest; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetNeedCheckPostServiceTest extends ServiceTest { + + @Autowired + private GetNeedCheckPostsService getNeedCheckPostsService; + + @Test + void 확인이_필요한_게시물을_조회한다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + + groupUsers.addUser(GroupUser.createGroupMember(bobId, group)); + + participants.saveWithUserIdAndQuestId(aliceId, questId); + participants.saveWithUserIdAndQuestId(bobId, questId); + + final Post post1 = POST_1.생성(aliceId, questId); + post1.needCheck(); + final Post post2 = POST_1.생성(aliceId, questId); + post2.needCheck(); + + final List actual = List.of(posts.save(post1).getId(), + posts.save(post2).getId()); + posts.save(POST_1.생성(bobId)); + + // when + final List expected = getNeedCheckPostsService.invoke(aliceId, group.getId()).posts() + .stream().map(SimplePostResponse::id).toList(); + + // then + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); + } + + @Test + void 관리자가_아니라면_조회할_수_없다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + + groupUsers.addUser(GroupUser.createGroupMember(bobId, group)); + + // when & then + assertThatThrownBy(() -> getNeedCheckPostsService.invoke(bobId, questId)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(NOT_GROUP_MANAGER.getMessage()); + } +} diff --git a/src/test/java/daybyquest/post/application/GetPostByGroupIdServiceTest.java b/src/test/java/daybyquest/post/application/GetPostByGroupIdServiceTest.java new file mode 100644 index 0000000..b635b1d --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetPostByGroupIdServiceTest.java @@ -0,0 +1,51 @@ +package daybyquest.post.application; + +import static daybyquest.support.fixture.GroupFixtures.GROUP_1; +import static daybyquest.support.fixture.InterestFixtures.INTEREST; +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static org.assertj.core.api.Assertions.assertThat; + +import daybyquest.group.domain.Group; +import daybyquest.group.domain.GroupUser; +import daybyquest.post.dto.response.PostResponse; +import daybyquest.quest.domain.Quest; +import daybyquest.support.test.ServiceTest; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetPostByGroupIdServiceTest extends ServiceTest { + + @Autowired + private GetPostByGroupIdService getPostByGroupIdService; + + @Test + void 그룹으로_게시물을_조회한다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + + groupUsers.addUser(GroupUser.createGroupMember(bobId, group)); + + participants.saveWithUserIdAndQuestId(aliceId, questId); + participants.saveWithUserIdAndQuestId(bobId, questId); + + final List actual = List.of(posts.save(POST_1.생성(aliceId, questId)).getId(), + posts.save(POST_1.생성(aliceId, questId)).getId(), + posts.save(POST_1.생성(bobId, questId)).getId()); + posts.save(POST_1.생성(bobId)); + + // when + final List expected = getPostByGroupIdService.invoke(aliceId, group.getId(), 페이지()).posts() + .stream().map(PostResponse::id).toList(); + + // then + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); + } +} diff --git a/src/test/java/daybyquest/post/application/GetPostByQuestIdServiceTest.java b/src/test/java/daybyquest/post/application/GetPostByQuestIdServiceTest.java new file mode 100644 index 0000000..31d36a8 --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetPostByQuestIdServiceTest.java @@ -0,0 +1,43 @@ +package daybyquest.post.application; + +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static org.assertj.core.api.Assertions.assertThat; + +import daybyquest.post.dto.response.PostResponse; +import daybyquest.support.fixture.BadgeFixtures; +import daybyquest.support.test.ServiceTest; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetPostByQuestIdServiceTest extends ServiceTest { + + @Autowired + private GetPostByQuestIdService getPostByQuestIdService; + + @Test + void 퀘스트로_게시물을_조회한다() { + // given + final Long aliceId = ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + + final Long badgeId = badges.save(BadgeFixtures.BADGE_1.생성()).getId(); + final Long questId = quests.save(QUEST_1.세부사항을_설정한다(QUEST_1.일반_퀘스트_생성(badgeId))).getId(); + + participants.saveWithUserIdAndQuestId(aliceId, questId); + participants.saveWithUserIdAndQuestId(bobId, questId); + + final List actual = List.of(posts.save(POST_1.생성(aliceId, questId)).getId(), + posts.save(POST_1.생성(aliceId, questId)).getId(), + posts.save(POST_1.생성(bobId, questId)).getId()); + posts.save(POST_1.생성(bobId)); + + // when + final List expected = getPostByQuestIdService.invoke(aliceId, questId, 페이지()).posts() + .stream().map(PostResponse::id).toList(); + + // then + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); + } +} diff --git a/src/test/java/daybyquest/post/application/GetPostByUsernameServiceTest.java b/src/test/java/daybyquest/post/application/GetPostByUsernameServiceTest.java new file mode 100644 index 0000000..441f314 --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetPostByUsernameServiceTest.java @@ -0,0 +1,36 @@ +package daybyquest.post.application; + +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.UserFixtures.ALICE; +import static org.assertj.core.api.Assertions.assertThat; + +import daybyquest.post.dto.response.PostResponse; +import daybyquest.support.test.ServiceTest; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetPostByUsernameServiceTest extends ServiceTest { + + @Autowired + private GetPostByUsernameService getPostByUsernameService; + + @Test + void 퀘스트로_게시물을_조회한다() { + // given + final Long aliceId = ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + + final List actual = List.of(posts.save(POST_1.생성(aliceId)).getId(), + posts.save(POST_1.생성(aliceId)).getId(), + posts.save(POST_1.생성(aliceId)).getId()); + posts.save(POST_1.생성(bobId)); + + // when + final List expected = getPostByUsernameService.invoke(aliceId, ALICE.username, 페이지()).posts() + .stream().map(PostResponse::id).toList(); + + // then + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); + } +} diff --git a/src/test/java/daybyquest/post/application/GetPostFromFollowingsServiceTest.java b/src/test/java/daybyquest/post/application/GetPostFromFollowingsServiceTest.java new file mode 100644 index 0000000..4ed1b25 --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetPostFromFollowingsServiceTest.java @@ -0,0 +1,42 @@ +package daybyquest.post.application; + +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static org.assertj.core.api.Assertions.assertThat; + +import daybyquest.post.dto.response.PostResponse; +import daybyquest.relation.domain.Follow; +import daybyquest.support.test.ServiceTest; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetPostFromFollowingsServiceTest extends ServiceTest { + + @Autowired + private GetPostFromFollowingService getPostFromFollowingService; + + @Test + void 팔로잉_게시물을_조회한다() { + // given + final Long aliceId = ALICE를_저장한다(); + final Long bobId = BOB을_저장한다(); + final Long charlieId = CHARLIE를_저장한다(); + final Long davidId = DAVID를_저장한다(); + + follows.save(new Follow(aliceId, bobId)); + follows.save(new Follow(aliceId, charlieId)); + + final List actual = List.of(posts.save(POST_1.생성(charlieId)).getId(), + posts.save(POST_1.생성(charlieId)).getId(), + posts.save(POST_1.생성(bobId)).getId()); + posts.save(POST_1.생성(aliceId)); + posts.save(POST_1.생성(davidId)); + + // when + final List expected = getPostFromFollowingService.invoke(aliceId, 페이지()).posts() + .stream().map(PostResponse::id).toList(); + + // then + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); + } +} diff --git a/src/test/java/daybyquest/post/application/GetPostServiceTest.java b/src/test/java/daybyquest/post/application/GetPostServiceTest.java new file mode 100644 index 0000000..c14e3d6 --- /dev/null +++ b/src/test/java/daybyquest/post/application/GetPostServiceTest.java @@ -0,0 +1,94 @@ +package daybyquest.post.application; + +import static daybyquest.support.fixture.BadgeFixtures.BADGE_1; +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static daybyquest.support.fixture.UserFixtures.ALICE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import daybyquest.badge.domain.Badges; +import daybyquest.participant.domain.Participants; +import daybyquest.post.domain.Posts; +import daybyquest.post.dto.response.PostWithQuestResponse; +import daybyquest.post.dto.response.PostWithQuestResponse.SimpleQuestResponse; +import daybyquest.quest.domain.Quest; +import daybyquest.quest.domain.Quests; +import daybyquest.support.test.ServiceTest; +import daybyquest.user.dto.response.ProfileResponse; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class GetPostServiceTest extends ServiceTest { + + @Autowired + private GetPostService getPostService; + + @Autowired + private Posts posts; + + @Autowired + private Quests quests; + + @Autowired + private Badges badges; + + @Autowired + private Participants participants; + + @Test + void 게시물을_조회한다() { + // given + final Long id = ALICE를_저장한다(); + final Long postId = posts.save(POST_1.생성(id)).getId(); + + // when + final PostWithQuestResponse response = getPostService.invoke(id, postId); + + // then + assertAll(() -> { + assertThat(response.id()).isEqualTo(postId); + assertThat(response.content()).isEqualTo(POST_1.content); + assertThat(response.imageIdentifiers()) + .containsExactlyInAnyOrderElementsOf(POST_1.imageIdentifiers); + }); + } + + @Test + void 회원_정보가_함께_조회된다() { + // given + final Long id = ALICE를_저장한다(); + final Long postId = posts.save(POST_1.생성(id)).getId(); + + // when + final ProfileResponse response = getPostService.invoke(id, postId).author(); + + // then + assertAll(() -> { + assertThat(response.username()).isEqualTo(ALICE.username); + assertThat(response.name()).isEqualTo(ALICE.name); + assertThat(response.imageIdentifier()).isEqualTo(ALICE.imageIdentifier); + }); + } + + @Test + void 퀘스트_정보가_함께_조회된다() { + // given + final Long id = ALICE를_저장한다(); + final Long badgeId = badges.save(BADGE_1.생성()).getId(); + final Quest quest = QUEST_1.일반_퀘스트_생성(badgeId); + QUEST_1.세부사항을_설정한다(quest); + final Long questId = quests.save(quest).getId(); + participants.saveWithUserIdAndQuestId(id, questId); + final Long postId = posts.save(POST_1.생성(id, questId)).getId(); + + // when + final SimpleQuestResponse response = getPostService.invoke(id, postId).quest(); + + // then + assertAll(() -> { + assertThat(response.questId()).isEqualTo(questId); + assertThat(response.title()).isEqualTo(QUEST_1.title); + }); + } +} diff --git a/src/test/java/daybyquest/post/application/GetTrackerServiceTest.java b/src/test/java/daybyquest/post/application/GetTrackerServiceTest.java index 1a45a9b..2525f7b 100644 --- a/src/test/java/daybyquest/post/application/GetTrackerServiceTest.java +++ b/src/test/java/daybyquest/post/application/GetTrackerServiceTest.java @@ -1,51 +1,47 @@ package daybyquest.post.application; +import static daybyquest.support.fixture.PostFixtures.POST_1; import static daybyquest.support.fixture.UserFixtures.ALICE; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import daybyquest.post.domain.Posts; import daybyquest.post.dto.response.TrackerResponse; -import daybyquest.post.query.PostDao; -import daybyquest.post.query.SimplePostData; -import daybyquest.user.domain.Users; +import daybyquest.support.test.ServiceTest; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.BDDMockito; -import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; -@ExtendWith(MockitoExtension.class) -public class GetTrackerServiceTest { +public class GetTrackerServiceTest extends ServiceTest { - private final Users users = BDDMockito.mock(Users.class); + @Autowired + private GetTrackerService getTrackerService; - private final PostDao postDao = BDDMockito.mock(PostDao.class); - - private final GetTrackerService getTrackerService = new GetTrackerService(users, postDao, 5L); + @Autowired + private Posts posts; @Test void 트래커를_조회한다() { // given - final Long loginId = 1L; - final Long aliceId = 2L; + final Long id = ALICE를_저장한다(); final LocalDateTime now = LocalDateTime.now(); - final List simplePostData = List.of( - new SimplePostData(1L, now), - new SimplePostData(2L, now.minusDays(1)), - new SimplePostData(3L, now.minusDays(1)), - new SimplePostData(4L, now.minusDays(3)), - new SimplePostData(4L, now.minusDays(4)) - ); - final List expected = List.of(1L, 2L, 0L, 1L, 1L); - given(users.getUserIdByUsername(ALICE.username)).willReturn(aliceId); - given(postDao.findAllBySuccessAndUploadedAtAfter(eq(aliceId), any())).willReturn(simplePostData); + given(dataTimeProvider.getNow()).willReturn(Optional.of(now)); + posts.save(POST_1.생성(id)); + given(dataTimeProvider.getNow()).willReturn(Optional.of(now.minusDays(1))); + posts.save(POST_1.생성(id)); + posts.save(POST_1.생성(id)); + given(dataTimeProvider.getNow()).willReturn(Optional.of(now.minusDays(3))); + posts.save(POST_1.생성(id)); + given(dataTimeProvider.getNow()).willReturn(Optional.of(now.minusDays(4))); + posts.save(POST_1.생성(id)); + + final List expected = List.of(1L, 2L, 0L, 1L, 1L); // when - final TrackerResponse response = getTrackerService.invoke(loginId, ALICE.username); + final TrackerResponse response = getTrackerService.invoke(id, ALICE.username); final List tracker = response.tracker(); // then diff --git a/src/test/java/daybyquest/post/application/JudgePostServiceTest.java b/src/test/java/daybyquest/post/application/JudgePostServiceTest.java new file mode 100644 index 0000000..b610ebb --- /dev/null +++ b/src/test/java/daybyquest/post/application/JudgePostServiceTest.java @@ -0,0 +1,160 @@ +package daybyquest.post.application; + +import static daybyquest.global.error.ExceptionCode.ALREADY_JUDGED_POST; +import static daybyquest.global.error.ExceptionCode.NOT_LINKED_POST; +import static daybyquest.post.domain.PostState.FAIL; +import static daybyquest.post.domain.PostState.NEED_CHECK; +import static daybyquest.post.domain.PostState.SUCCESS; +import static daybyquest.support.fixture.GroupFixtures.GROUP_1; +import static daybyquest.support.fixture.InterestFixtures.INTEREST; +import static daybyquest.support.fixture.PostFixtures.POST_1; +import static daybyquest.support.fixture.QuestFixtures.QUEST_1; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import daybyquest.global.error.exception.InvalidDomainException; +import daybyquest.group.domain.Group; +import daybyquest.post.domain.Post; +import daybyquest.post.dto.request.JudgePostRequest; +import daybyquest.quest.domain.Quest; +import daybyquest.support.fixture.BadgeFixtures; +import daybyquest.support.test.ServiceTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.util.ReflectionTestUtils; + +public class JudgePostServiceTest extends ServiceTest { + + @Autowired + private JudgePostService judgePostService; + + @Test + void 일반_퀘스트가_링크된_게시물을_성공_판정한다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + + final Long badgeId = badges.save(BadgeFixtures.BADGE_1.생성()).getId(); + final Long questId = quests.save(QUEST_1.세부사항을_설정한다(QUEST_1.일반_퀘스트_생성(badgeId))).getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Long postId = posts.save(POST_1.생성(aliceId, questId)).getId(); + + final JudgePostRequest request = 게시물_판정_요청("SUCCESS"); + + // when + judgePostService.invoke(postId, request); + + // then + final Post post = posts.getById(postId); + assertThat(post.getState()).isEqualTo(SUCCESS); + } + + @Test + void 그룹_퀘스트가_링크된_게시물을_성공_판정한다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Long postId = posts.save(POST_1.생성(aliceId, questId)).getId(); + + final JudgePostRequest request = 게시물_판정_요청("SUCCESS"); + + // when + judgePostService.invoke(postId, request); + + // then + final Post post = posts.getById(postId); + assertThat(post.getState()).isEqualTo(SUCCESS); + } + + @Test + void 일반_퀘스트가_링크된_게시물을_실패_판정한다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + + final Long badgeId = badges.save(BadgeFixtures.BADGE_1.생성()).getId(); + final Long questId = quests.save(QUEST_1.세부사항을_설정한다(QUEST_1.일반_퀘스트_생성(badgeId))).getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Long postId = posts.save(POST_1.생성(aliceId, questId)).getId(); + + final JudgePostRequest request = 게시물_판정_요청("FAIL"); + + // when + judgePostService.invoke(postId, request); + + // then + final Post post = posts.getById(postId); + assertThat(post.getState()).isEqualTo(FAIL); + } + + @Test + void 그룹_퀘스트가_링크된_게시물을_실패_판정하면_확인_필요_상태가_된다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + interests.save(INTEREST.생성()); + + final Group group = groups.save(aliceId, GROUP_1.생성()); + final Quest quest = quests.save(QUEST_1.보상_없이_세부사항을_설정한다(QUEST_1.그룹_퀘스트_생성(group))); + final Long questId = quest.getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Long postId = posts.save(POST_1.생성(aliceId, questId)).getId(); + + final JudgePostRequest request = 게시물_판정_요청("FAIL"); + + // when + judgePostService.invoke(postId, request); + + // then + final Post post = posts.getById(postId); + assertThat(post.getState()).isEqualTo(NEED_CHECK); + } + + @Test + void 퀘스트가_링크되지_않은_게시물은_판정할_수_없다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + + final Long postId = posts.save(POST_1.생성(aliceId)).getId(); + + final JudgePostRequest request = 게시물_판정_요청("FAIL"); + + // when + assertThatThrownBy(() -> judgePostService.invoke(postId, request)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(NOT_LINKED_POST.getMessage()); + } + + @Test + void 이미_판정된_게시물은_판정할_수_없다() { + // given + final Long aliceId = 중재자_권한으로_ALICE를_저장한다(); + + final Long badgeId = badges.save(BadgeFixtures.BADGE_1.생성()).getId(); + final Long questId = quests.save(QUEST_1.세부사항을_설정한다(QUEST_1.일반_퀘스트_생성(badgeId))).getId(); + participants.saveWithUserIdAndQuestId(aliceId, questId); + + final Post post = POST_1.생성(aliceId, questId); + post.success(); + final Long postId = posts.save(post).getId(); + + final JudgePostRequest request = 게시물_판정_요청("FAIL"); + + // when + assertThatThrownBy(() -> judgePostService.invoke(postId, request)) + .isInstanceOf(InvalidDomainException.class) + .hasMessageContaining(ALREADY_JUDGED_POST.getMessage()); + } + + private JudgePostRequest 게시물_판정_요청(final String judgement) { + final JudgePostRequest request = new JudgePostRequest(); + ReflectionTestUtils.setField(request, "judgement", judgement); + return request; + } +} diff --git a/src/test/java/daybyquest/support/fixture/InterestFixtures.java b/src/test/java/daybyquest/support/fixture/InterestFixtures.java index 8f2e3ca..b2c7d2f 100644 --- a/src/test/java/daybyquest/support/fixture/InterestFixtures.java +++ b/src/test/java/daybyquest/support/fixture/InterestFixtures.java @@ -9,7 +9,8 @@ public enum InterestFixtures { INTEREST_1("관심사1", "관심사사진1"), INTEREST_2("관심사2", "관심사사진2"), INTEREST_3("관심사3", "관심사사진3"), - INTEREST_4("관심사4", "관심사사진4"); + INTEREST_4("관심사4", "관심사사진4"), + INTEREST("관심사", "관심사사진"); public final String name; diff --git a/src/test/java/daybyquest/support/fixture/QuestFixtures.java b/src/test/java/daybyquest/support/fixture/QuestFixtures.java index cf70e36..4d032dc 100644 --- a/src/test/java/daybyquest/support/fixture/QuestFixtures.java +++ b/src/test/java/daybyquest/support/fixture/QuestFixtures.java @@ -87,12 +87,14 @@ public enum QuestFixtures { return Quest.createGroupQuest(group.getId(), imageDescription, 사진_목록(), group.getImage()); } - public void 세부사항을_설정한다(final Quest quest) { + public Quest 세부사항을_설정한다(final Quest quest) { quest.setDetail(title, content, interest, expiredAt, label, rewardCount); + return quest; } - public void 보상_없이_세부사항을_설정한다(final Quest quest) { + public Quest 보상_없이_세부사항을_설정한다(final Quest quest) { quest.setDetail(title, content, interest, expiredAt, label, null); + return quest; } public List 사진_목록() { diff --git a/src/test/java/daybyquest/support/test/ServiceTest.java b/src/test/java/daybyquest/support/test/ServiceTest.java index 3a3d6a5..d4af9dc 100644 --- a/src/test/java/daybyquest/support/test/ServiceTest.java +++ b/src/test/java/daybyquest/support/test/ServiceTest.java @@ -6,13 +6,27 @@ import static daybyquest.support.fixture.UserFixtures.DARTH; import static daybyquest.support.fixture.UserFixtures.DAVID; +import daybyquest.badge.domain.Badges; import daybyquest.global.query.NoOffsetIdPage; +import daybyquest.group.domain.GroupUsers; +import daybyquest.group.domain.Groups; +import daybyquest.interest.domain.Interests; +import daybyquest.participant.domain.Participants; +import daybyquest.post.domain.Posts; +import daybyquest.quest.domain.Quests; +import daybyquest.relation.domain.Follows; import daybyquest.support.config.StubInfraConfig; import daybyquest.support.util.DatabaseCleaner; +import daybyquest.user.domain.User; import daybyquest.user.domain.Users; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.data.auditing.AuditingHandler; +import org.springframework.data.auditing.DateTimeProvider; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; @@ -26,11 +40,58 @@ public class ServiceTest { @Autowired protected Users users; + @Autowired + protected Posts posts; + + @Autowired + protected Groups groups; + + @Autowired + protected GroupUsers groupUsers; + + @Autowired + protected Quests quests; + + @Autowired + protected Badges badges; + + @Autowired + protected Participants participants; + + @Autowired + protected Interests interests; + + @Autowired + protected Follows follows; + + @MockBean + protected DateTimeProvider dataTimeProvider; + + @SpyBean + private AuditingHandler handler; + + @BeforeEach + void setUp() { + handler.setDateTimeProvider(dataTimeProvider); + } + @AfterEach void cleanDatabase() { cleaner.clean(); } + protected Long 중재자_권한으로_ALICE를_저장한다() { + final User user = ALICE.생성(); + user.promote(); + return users.save(user).getId(); + } + + protected Long 중재자_권한으로_BOB을_저장한다() { + final User user = BOB.생성(); + user.promote(); + return users.save(user).getId(); + } + protected Long ALICE를_저장한다() { return users.save(ALICE.생성()).getId(); } diff --git a/src/test/java/daybyquest/user/application/UpdateUserInterestServiceTest.java b/src/test/java/daybyquest/user/application/UpdateUserInterestServiceTest.java index 997c746..02ae68c 100644 --- a/src/test/java/daybyquest/user/application/UpdateUserInterestServiceTest.java +++ b/src/test/java/daybyquest/user/application/UpdateUserInterestServiceTest.java @@ -8,13 +8,12 @@ import daybyquest.global.error.exception.NotExistInterestException; import daybyquest.interest.domain.Interests; import daybyquest.support.test.ServiceTest; -import daybyquest.user.domain.User; import daybyquest.user.dto.request.UpdateUserInterestRequest; +import java.util.List; import java.util.Set; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.transaction.annotation.Transactional; public class UpdateUserInterestServiceTest extends ServiceTest { @@ -25,21 +24,20 @@ public class UpdateUserInterestServiceTest extends ServiceTest { private Interests interests; @Test - @Transactional void 사용자_관심사를_수정한다() { // given final Long id = ALICE를_저장한다(); interests.save(INTEREST_1.생성()); interests.save(INTEREST_2.생성()); - final Set interests = Set.of(INTEREST_1.name, INTEREST_2.name); - final UpdateUserInterestRequest request = 사용자_관심사_수정_요청(interests); + final Set expected = Set.of(INTEREST_1.name, INTEREST_2.name); + final UpdateUserInterestRequest request = 사용자_관심사_수정_요청(expected); // when updateUserInterestService.invoke(id, request); // then - final User user = users.getById(id); - assertThat(user.getInterests()).containsExactlyInAnyOrderElementsOf(interests); + final List actual = users.getById(id).getInterests(); + assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); } @Test diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 0a1ed79..f355eb8 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -36,4 +36,4 @@ image: user-identifier: base.png tracker: - days: 60 \ No newline at end of file + days: 5 \ No newline at end of file