diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java index 386ed7a1e..1c07fff4e 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java @@ -1,5 +1,6 @@ package site.timecapsulearchive.core.common.fixture.domain; +import java.lang.reflect.Field; import java.time.ZonedDateTime; import java.util.List; import java.util.stream.IntStream; @@ -91,4 +92,27 @@ public static Capsule groupCapsule(Member member, CapsuleSkin capsuleSkin, Group .group(group) .build(); } + + public static Capsule groupCapsuleWithCapsuleId( + Member member, + CapsuleSkin capsuleSkin, + Group group, + Long capsuleId + ) { + try { + Capsule capsule = groupCapsule(member, capsuleSkin, group); + + setFieldValue(capsule, "id", capsuleId); + return capsule; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void setFieldValue(Object instance, String fieldName, Object value) + throws NoSuchFieldException, IllegalAccessException { + Field field = instance.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(instance, value); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java index 795913fd7..7b0c0c6bc 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java @@ -1,7 +1,10 @@ package site.timecapsulearchive.core.common.fixture.domain; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; @@ -33,4 +36,19 @@ public static Optional groupCapsuleOpen(int dataPrefix) { ) ); } + + public static List groupCapsuleOpensNotAllOpened( + Capsule capsule, + List groupMembers + ) { + int mid = groupMembers.size() / 2; + List opened = groupCapsuleOpens(true, capsule, + groupMembers.subList(0, mid)); + List notOpened = groupCapsuleOpens(false, capsule, + groupMembers.subList(mid, groupMembers.size() - 1)); + + return Stream.of(opened, notOpened) + .flatMap(Collection::stream) + .toList(); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java index e7f245f2d..4a9c6c10d 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java @@ -37,13 +37,11 @@ class GroupCapsuleOpenQueryRepositoryTest extends RepositoryTest { private List groupCapsuleOpens; public GroupCapsuleOpenQueryRepositoryTest( - JPAQueryFactory jpaQueryFactory, JdbcTemplate jdbcTemplate, DataSource dataSource ) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - this.groupCapsuleOpenRepository = new GroupCapsuleOpenQueryRepository(jdbcTemplate, - jpaQueryFactory); + this.groupCapsuleOpenRepository = new GroupCapsuleOpenQueryRepository(jdbcTemplate); } @Transactional diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java index c6caa072a..20a6ffb87 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java @@ -1,28 +1,34 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.service; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; import java.util.Optional; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import site.timecapsulearchive.core.common.fixture.domain.CapsuleFixture; +import site.timecapsulearchive.core.common.fixture.domain.CapsuleSkinFixture; import site.timecapsulearchive.core.common.fixture.domain.GroupCapsuleOpenFixture; +import site.timecapsulearchive.core.common.fixture.domain.GroupFixture; +import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; +import site.timecapsulearchive.core.domain.capsule.entity.Capsule; +import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; +import site.timecapsulearchive.core.domain.capsule.exception.CapsuleNotFondException; import site.timecapsulearchive.core.domain.capsule.exception.GroupCapsuleOpenNotFoundException; import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.generic_capsule.repository.CapsuleRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; -import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenQueryRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; +import site.timecapsulearchive.core.domain.member.entity.Member; import site.timecapsulearchive.core.global.error.ErrorCode; class GroupCapsuleServiceTest { @@ -35,13 +41,9 @@ class GroupCapsuleServiceTest { GroupCapsuleQueryRepository.class); private final GroupCapsuleOpenRepository groupCapsuleOpenRepository = mock( GroupCapsuleOpenRepository.class); - private final GroupCapsuleOpenQueryRepository groupCapsuleOpenQueryRepository = mock( - GroupCapsuleOpenQueryRepository.class); private final GroupCapsuleService groupCapsuleService = new GroupCapsuleService( - capsuleRepository, groupCapsuleQueryRepository, groupCapsuleOpenRepository, - groupCapsuleOpenQueryRepository - ); + capsuleRepository, groupCapsuleQueryRepository, groupCapsuleOpenRepository); @Test void 개봉된_그룹_캡슐의_상세_내용을_볼_수_있다() { @@ -201,14 +203,14 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(Optional.empty()); //when //then assertThatThrownBy(() -> groupCapsuleService.openGroupCapsule(memberId, capsuleId)) - .isInstanceOf(GroupCapsuleOpenNotFoundException.class) - .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); + .isInstanceOf(CapsuleNotFondException.class) + .hasMessageContaining(ErrorCode.CAPSULE_NOT_FOUND_ERROR.getMessage()); } @Test @@ -216,17 +218,35 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) - .willReturn(GroupCapsuleOpenFixture.groupCapsuleOpen(memberId.intValue())); - given(groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId(anyLong())) - .willReturn(List.of(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE)); + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpens(false, groupCapsule.get(), groupMembers) + ); //when groupCapsuleService.openGroupCapsule(memberId, capsuleId); //then - verifyNoInteractions(capsuleRepository); + assertThat(groupCapsule.get().getIsOpened()).isFalse(); + } + + private Optional getGroupCapsule(Long memberId, Long capsuleId) { + Member member = MemberFixture.memberWithMemberId(memberId); + + return Optional.ofNullable( + CapsuleFixture.groupCapsuleWithCapsuleId( + member, + CapsuleSkinFixture.capsuleSkin(member), + GroupFixture.group(), + capsuleId + ) + ); } @Test @@ -234,15 +254,63 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) - .willReturn(GroupCapsuleOpenFixture.groupCapsuleOpen(memberId.intValue())); - given(groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId(anyLong())) - .willReturn(List.of(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)); + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpens(true, groupCapsule.get(), groupMembers) + ); //when groupCapsuleService.openGroupCapsule(memberId, capsuleId); //then - verify(capsuleRepository, times(1)).updateIsOpenedTrue(anyLong(), anyLong()); + assertThat(groupCapsule.get().getIsOpened()).isTrue(); + } + + @Test + void 일부_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉되지_않는다() { + //given + Long memberId = 1L; + Long capsuleId = 1L; + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpensNotAllOpened(groupCapsule.get(), groupMembers) + ); + + //when + groupCapsuleService.openGroupCapsule(memberId, capsuleId); + + //then + assertThat(groupCapsule.get().getIsOpened()).isFalse(); + } + + @Test + void 모든_그룹원이_캡슐을_개봉이_없는_경우_예외가_발생한다() { + //given + Long memberId = 1L; + Long capsuleId = 1L; + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)).willReturn( + Collections.emptyList()); + + //when + //then + assertThatThrownBy(() -> groupCapsuleService.openGroupCapsule(memberId, capsuleId)) + .isInstanceOf(GroupCapsuleOpenNotFoundException.class) + .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); } }