diff --git a/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java b/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java index 1f836b9..34601a3 100644 --- a/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java +++ b/src/main/java/com/swyp/picke/global/infra/fcm/service/FcmPushService.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.HashMap; import java.util.Map; @Slf4j @@ -23,9 +24,13 @@ public class FcmPushService { * iOS는 FCM을 거치지 않고 ApnsPushService가 APNs로 직접 발송한다. */ public void send(UserDevice device, String title, String body, Map data) { + Map payload = new HashMap<>(data); + payload.put("title", title); + payload.put("body", body); + Message message = Message.builder() .setToken(device.getFcmToken()) - .putAllData(data) + .putAllData(payload) .setAndroidConfig(AndroidConfig.builder() .setPriority(AndroidConfig.Priority.HIGH) .build()) diff --git a/src/test/java/com/swyp/picke/global/infra/fcm/service/FcmPushServiceTest.java b/src/test/java/com/swyp/picke/global/infra/fcm/service/FcmPushServiceTest.java new file mode 100644 index 0000000..3b0f818 --- /dev/null +++ b/src/test/java/com/swyp/picke/global/infra/fcm/service/FcmPushServiceTest.java @@ -0,0 +1,59 @@ +package com.swyp.picke.global.infra.fcm.service; + +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.Message; +import com.swyp.picke.domain.notification.entity.UserDevice; +import com.swyp.picke.domain.notification.enums.DevicePlatform; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.lang.reflect.Field; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class FcmPushServiceTest { + + @Mock + private FirebaseMessaging firebaseMessaging; + + @Test + void send_includes_title_and_body_in_data_payload() throws Exception { + FcmPushService fcmPushService = new FcmPushService(firebaseMessaging); + UserDevice device = buildDevice(); + + fcmPushService.send(device, "제목", "본문", Map.of("type", "TEST")); + + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(firebaseMessaging).send(messageCaptor.capture()); + + Map data = extractData(messageCaptor.getValue()); + assertThat(data).containsEntry("title", "제목"); + assertThat(data).containsEntry("body", "본문"); + assertThat(data).containsEntry("type", "TEST"); + } + + @SuppressWarnings("unchecked") + private Map extractData(Message message) throws Exception { + Field dataField = Message.class.getDeclaredField("data"); + dataField.setAccessible(true); + return (Map) dataField.get(message); + } + + private UserDevice buildDevice() throws Exception { + UserDevice device = UserDevice.builder() + .fcmToken("token") + .platform(DevicePlatform.ANDROID) + .build(); + Field idField = device.getClass().getSuperclass().getDeclaredField("id"); + idField.setAccessible(true); + idField.set(device, 1L); + return device; + } +}