diff --git a/mysql/initdb.d/item-data.sql b/mysql/initdb.d/item-data.sql index 7030418f..28561b81 100644 --- a/mysql/initdb.d/item-data.sql +++ b/mysql/initdb.d/item-data.sql @@ -37,3 +37,12 @@ values ('MORNING', 'SKIN', '산타 오목눈이', 'https://image.moabam.com/moab insert into item (type, category, name, awake_image, sleep_image, bug_price, golden_bug_price, unlock_level, created_at) values ('NIGHT', 'SKIN', '산타 부엉이', 'https://image.moabam.com/moabam/skins/owl/santa/eyes-opened.png', 'https://image.moabam.com/moabam/skins/owl/santa/eyes-closed', 30, 15, 15, current_time()); + +insert into product (id, type, name, price, quantity, created_at, updated_at) +values (null, 'BUG', '황금벌레x5', 3300, 5, current_time(), null); + +insert into product (id, type, name, price, quantity, created_at, updated_at) +values (null, 'BUG', '황금벌레x10', 6600, 10, current_time(), null); + +insert into product (id, type, name, price, quantity, created_at, updated_at) +values (null, 'BUG', '황금벌레x15', 9900, 15, current_time(), null); diff --git a/src/main/java/com/moabam/api/application/notification/NotificationService.java b/src/main/java/com/moabam/api/application/notification/NotificationService.java index 41ca7539..523ac965 100644 --- a/src/main/java/com/moabam/api/application/notification/NotificationService.java +++ b/src/main/java/com/moabam/api/application/notification/NotificationService.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.moabam.api.application.member.MemberService; import com.moabam.api.application.room.RoomService; import com.moabam.api.domain.notification.repository.NotificationRepository; import com.moabam.api.domain.room.Participant; @@ -29,24 +30,27 @@ public class NotificationService { private static final String COMMON_TITLE = "모아밤"; - private static final String KNOCK_BODY = "%s방에서 %s님이 콕 찔렀어요~"; - private static final String CERTIFY_TIME_BODY = "%s방 인증 시간~"; + private static final String KNOCK_BODY = "[%s] - [%s]님이 콕콕콕!"; + private static final String CERTIFY_TIME_BODY = "[%s] - 인증 시간!"; private final ClockHolder clockHolder; private final FcmService fcmService; private final RoomService roomService; + private final MemberService memberService; private final NotificationRepository notificationRepository; private final ParticipantSearchRepository participantSearchRepository; @Transactional - public void sendKnock(Long roomId, Long targetId, Long memberId, String memberNickname) { - String roomTitle = roomService.findRoom(roomId).getTitle(); + public void sendKnock(Long roomId, Long targetId, Long memberId) { validateConflictKnock(roomId, targetId, memberId); String fcmToken = fcmService.findTokenByMemberId(targetId) .orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_FCM_TOKEN)); + String roomTitle = roomService.findRoom(roomId).getTitle(); + String memberNickname = memberService.findMember(memberId).getNickname(); String notificationTitle = roomId.toString(); + String notificationBody = String.format(KNOCK_BODY, roomTitle, memberNickname); fcmService.sendAsync(fcmToken, notificationTitle, notificationBody); notificationRepository.saveKnock(roomId, targetId, memberId); diff --git a/src/main/java/com/moabam/api/presentation/NotificationController.java b/src/main/java/com/moabam/api/presentation/NotificationController.java index 6b5287d9..85434343 100644 --- a/src/main/java/com/moabam/api/presentation/NotificationController.java +++ b/src/main/java/com/moabam/api/presentation/NotificationController.java @@ -31,7 +31,7 @@ public void sendKnock( @PathVariable("memberId") Long memberId, @Auth AuthMember authMember ) { - notificationService.sendKnock(roomId, memberId, authMember.id(), authMember.nickname()); + notificationService.sendKnock(roomId, memberId, authMember.id()); } @PostMapping diff --git a/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java b/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java index 10e0cdc9..a08d2b06 100644 --- a/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java +++ b/src/test/java/com/moabam/api/application/notification/NotificationServiceTest.java @@ -16,7 +16,9 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import com.moabam.api.application.member.MemberService; import com.moabam.api.application.room.RoomService; +import com.moabam.api.domain.member.Member; import com.moabam.api.domain.notification.repository.NotificationRepository; import com.moabam.api.domain.room.Participant; import com.moabam.api.domain.room.Room; @@ -30,6 +32,7 @@ import com.moabam.global.error.model.ErrorMessage; import com.moabam.support.annotation.WithMember; import com.moabam.support.common.FilterProcessExtension; +import com.moabam.support.fixture.MemberFixture; import com.moabam.support.fixture.RoomFixture; @ExtendWith({MockitoExtension.class, FilterProcessExtension.class}) @@ -38,6 +41,9 @@ class NotificationServiceTest { @InjectMocks NotificationService notificationService; + @Mock + MemberService memberService; + @Mock RoomService roomService; @@ -60,44 +66,59 @@ class NotificationServiceTest { void sendKnock_success() { // Given Room room = RoomFixture.room(); + Member member = MemberFixture.member(); given(roomService.findRoom(any(Long.class))).willReturn(room); + given(memberService.findMember(any(Long.class))).willReturn(member); given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.of("FCM-TOKEN")); given(notificationRepository.existsKnockByKey(any(Long.class), any(Long.class), any(Long.class))) .willReturn(false); // When - notificationService.sendKnock(1L, 1L, 2L, "nickName"); + notificationService.sendKnock(1L, 1L, 2L); // Then verify(fcmService).sendAsync(any(String.class), any(String.class), any(String.class)); verify(notificationRepository).saveKnock(any(Long.class), any(Long.class), any(Long.class)); } - @DisplayName("콕 찌를 상대의 방이 존재하지 않는다. - NotFoundException") + @DisplayName("콕 찌를 때, 방이 존재하지 않는다. - NotFoundException") @Test void sendKnock_Room_NotFoundException() { // Given given(roomService.findRoom(any(Long.class))).willThrow(NotFoundException.class); + given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.of("FCM-TOKEN")); // When & Then - assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L, "nickName")) + assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L)) .isInstanceOf(NotFoundException.class); } - @DisplayName("콕 찌를 상대의 FCM 토큰이 존재하지 않는다. - NotFoundException") + @DisplayName("콕 찌를 상대가 존재하지 않는다. - NotFoundException") @Test - void sendKnock_FcmToken_NotFoundException() { + void sendKnock_Member_NotFoundException() { // Given Room room = RoomFixture.room(); given(roomService.findRoom(any(Long.class))).willReturn(room); + given(memberService.findMember(any(Long.class))).willThrow(NotFoundException.class); + given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.of("FCM-TOKEN")); + + // When & Then + assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L)) + .isInstanceOf(NotFoundException.class); + } + + @DisplayName("콕 찌를 상대의 FCM 토큰이 존재하지 않는다. - NotFoundException") + @Test + void sendKnock_FcmToken_NotFoundException() { + // Given given(fcmService.findTokenByMemberId(any(Long.class))).willReturn(Optional.empty()); given(notificationRepository.existsKnockByKey(any(Long.class), any(Long.class), any(Long.class))) .willReturn(false); // When & Then - assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L, "nickName")) + assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L)) .isInstanceOf(NotFoundException.class) .hasMessage(ErrorMessage.NOT_FOUND_FCM_TOKEN.getMessage()); } @@ -106,14 +127,11 @@ void sendKnock_FcmToken_NotFoundException() { @Test void sendKnock_ConflictException() { // Given - Room room = RoomFixture.room(); - - given(roomService.findRoom(any(Long.class))).willReturn(room); given(notificationRepository.existsKnockByKey(any(Long.class), any(Long.class), any(Long.class))) .willReturn(true); // When & Then - assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L, "nickName")) + assertThatThrownBy(() -> notificationService.sendKnock(1L, 1L, 2L)) .isInstanceOf(ConflictException.class) .hasMessage(ErrorMessage.CONFLICT_KNOCK.getMessage()); } diff --git a/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java b/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java index 400ce3ee..b623bcb9 100644 --- a/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java +++ b/src/test/java/com/moabam/api/presentation/NotificationControllerTest.java @@ -8,9 +8,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -41,6 +42,7 @@ @SpringBootTest @AutoConfigureMockMvc @AutoConfigureRestDocs +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class NotificationControllerTest extends WithoutFilterSupporter { @Autowired @@ -67,15 +69,17 @@ class NotificationControllerTest extends WithoutFilterSupporter { @MockBean FirebaseMessaging firebaseMessaging; + Member member; Member target; Room room; String knockKey; - @BeforeEach + @BeforeAll void setUp() { - target = memberRepository.save(MemberFixture.member("123")); + member = memberRepository.save(MemberFixture.member(1L)); + target = memberRepository.save(MemberFixture.member("socialId")); room = roomRepository.save(RoomFixture.room()); - knockKey = String.format("room_%s_member_%s_knocks_%s", room.getId(), 1, target.getId()); + knockKey = String.format("roomId=%s_targetId=%s_memberId=%s", room.getId(), target.getId(), member.getId()); willReturn(null) .given(firebaseMessaging)