From 2d0cf0f1a509bf62eecaa099b589d1222167a96b Mon Sep 17 00:00:00 2001 From: 5803024019 Date: Fri, 15 May 2026 22:22:47 +0700 Subject: [PATCH] test: add AgoraTokenServiceTest unit test --- .../service/AgoraTokenServiceTest.java | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 walkguide-backend/demo/src/test/java/com/walkguide/service/AgoraTokenServiceTest.java diff --git a/walkguide-backend/demo/src/test/java/com/walkguide/service/AgoraTokenServiceTest.java b/walkguide-backend/demo/src/test/java/com/walkguide/service/AgoraTokenServiceTest.java new file mode 100644 index 0000000..7eb60bd --- /dev/null +++ b/walkguide-backend/demo/src/test/java/com/walkguide/service/AgoraTokenServiceTest.java @@ -0,0 +1,166 @@ +package com.walkguide.service; + +import com.walkguide.dto.response.AgoraTokenResponse; +import com.walkguide.entity.User; +import com.walkguide.exception.ResourceNotFoundException; +import com.walkguide.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.Instant; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +@DisplayName("AgoraTokenService Unit Tests") +class AgoraTokenServiceTest { + + @Mock + UserRepository userRepository; + + @InjectMocks + AgoraTokenService agoraTokenService; + + private User caller; + private User receiver; + + @BeforeEach + void setUp() { + caller = User.builder() + .id(3L) + .email("caller@test.com") + .displayName("Caller User") + .role("ROLE_USER") + .build(); + + receiver = User.builder() + .id(7L) + .email("receiver@test.com") + .displayName("Receiver Guardian") + .role("ROLE_GUARDIAN") + .build(); + } + + // ===== generateToken - Mode Demo (tanpa App ID/Certificate) ===== + + @Test + @DisplayName("generateToken - mode demo (appId kosong): token harus string kosong") + void generateToken_demoMode_shouldReturnEmptyToken() { + // appId dan appCertificate kosong (default @Value) + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + + AgoraTokenResponse result = agoraTokenService.generateToken(3L, 7L); + + assertThat(result).isNotNull(); + assertThat(result.getToken()).isEmpty(); + assertThat(result.getChannelName()).isEqualTo("call_3_7"); + assertThat(result.getAppId()).isEmpty(); + assertThat(result.getCallerName()).isEqualTo("Caller User"); + assertThat(result.getUid()).isEqualTo((int) (3L % Integer.MAX_VALUE)); + } + + @Test + @DisplayName("generateToken - channel name harus deterministik: call_{min}_{max}") + void generateToken_channelName_shouldBeDeterministicWithMinMax() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + + AgoraTokenResponse result1 = agoraTokenService.generateToken(3L, 7L); + + // Caller dan receiver dibalik — channel name tetap sama + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + AgoraTokenResponse result2 = agoraTokenService.generateToken(7L, 3L); + + assertThat(result1.getChannelName()).isEqualTo("call_3_7"); + assertThat(result2.getChannelName()).isEqualTo("call_3_7"); + } + + @Test + @DisplayName("generateToken - expiresAt harus ~1 jam dari sekarang") + void generateToken_expiresAt_shouldBeOneHourFromNow() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + + long before = Instant.now().getEpochSecond(); + AgoraTokenResponse result = agoraTokenService.generateToken(3L, 7L); + long after = Instant.now().getEpochSecond(); + + // expiresAt harus antara now+3600 dan now+3601 (toleransi 1 detik) + assertThat(result.getExpiresAt()).isBetween(before + 3600, after + 3601); + } + + @Test + @DisplayName("generateToken - mode produksi (appId+cert valid): token harus diawali '006'") + void generateToken_productionMode_shouldReturnTokenStartingWith006() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", "abcdef1234567890abcdef1234567890"); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", "aabbccddeeff00112233445566778899"); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + + AgoraTokenResponse result = agoraTokenService.generateToken(3L, 7L); + + assertThat(result.getToken()).startsWith("006"); + assertThat(result.getAppId()).isEqualTo("abcdef1234567890abcdef1234567890"); + } + + @Test + @DisplayName("generateToken - caller tidak ditemukan harus throw ResourceNotFoundException") + void generateToken_callerNotFound_shouldThrow() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(99L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> agoraTokenService.generateToken(99L, 7L)) + .isInstanceOf(ResourceNotFoundException.class) + .hasMessageContaining("Caller not found"); + } + + @Test + @DisplayName("generateToken - receiver tidak ditemukan harus throw ResourceNotFoundException") + void generateToken_receiverNotFound_shouldThrow() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(99L)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> agoraTokenService.generateToken(3L, 99L)) + .isInstanceOf(ResourceNotFoundException.class) + .hasMessageContaining("Receiver not found"); + } + + @Test + @DisplayName("generateToken - uid harus modulo Integer.MAX_VALUE dari callerId") + void generateToken_uid_shouldBeCallerIdModMaxInt() { + ReflectionTestUtils.setField(agoraTokenService, "agoraAppId", ""); + ReflectionTestUtils.setField(agoraTokenService, "agoraAppCertificate", ""); + + when(userRepository.findById(3L)).thenReturn(Optional.of(caller)); + when(userRepository.findById(7L)).thenReturn(Optional.of(receiver)); + + AgoraTokenResponse result = agoraTokenService.generateToken(3L, 7L); + + assertThat(result.getUid()).isEqualTo((int) (3L % Integer.MAX_VALUE)); + } +} \ No newline at end of file