test: add PairingServiceTest unit test
This commit is contained in:
parent
bfcfd4e0f5
commit
70487e6d0d
@ -0,0 +1,217 @@
|
||||
package com.walkguide.service;
|
||||
|
||||
import com.walkguide.dto.response.PairingStatusResponse;
|
||||
import com.walkguide.entity.PairingRelation;
|
||||
import com.walkguide.entity.User;
|
||||
import com.walkguide.enums.PairingStatus;
|
||||
import com.walkguide.exception.PairingException;
|
||||
import com.walkguide.exception.ResourceNotFoundException;
|
||||
import com.walkguide.repository.*;
|
||||
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 java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@DisplayName("PairingService Unit Tests")
|
||||
class PairingServiceTest {
|
||||
|
||||
@Mock PairingRelationRepository pairingRelationRepository;
|
||||
@Mock UserRepository userRepository;
|
||||
@Mock VoiceCommandConfigRepository voiceCommandConfigRepository;
|
||||
@Mock HardwareShortcutRepository hardwareShortcutRepository;
|
||||
@Mock AiConfigRepository aiConfigRepository;
|
||||
@Mock ActivityLogService activityLogService;
|
||||
@Mock FcmService fcmService;
|
||||
|
||||
@InjectMocks PairingService pairingService;
|
||||
|
||||
private User guardian;
|
||||
private User user;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
guardian = User.builder()
|
||||
.id(1L)
|
||||
.email("guardian@test.com")
|
||||
.role("ROLE_GUARDIAN")
|
||||
.displayName("Guardian Test")
|
||||
.fcmToken("guardian-fcm-token")
|
||||
.build();
|
||||
|
||||
user = User.builder()
|
||||
.id(2L)
|
||||
.email("user@test.com")
|
||||
.role("ROLE_USER")
|
||||
.displayName("User Test")
|
||||
.uniqueUserId("ABC123DEF456")
|
||||
.fcmToken("user-fcm-token")
|
||||
.build();
|
||||
}
|
||||
|
||||
// ===== INVITE USER TESTS =====
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - berhasil mengirim invite ke user yang valid")
|
||||
void inviteUser_success_shouldSavePairingAndSendFcm() {
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.PENDING)).thenReturn(false);
|
||||
when(userRepository.findById(1L)).thenReturn(Optional.of(guardian));
|
||||
when(userRepository.findByUniqueUserId("ABC123DEF456")).thenReturn(Optional.of(user));
|
||||
when(pairingRelationRepository.existsByUser_IdAndStatus(2L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.save(any(PairingRelation.class))).thenAnswer(inv -> {
|
||||
PairingRelation p = inv.getArgument(0);
|
||||
p.setId(10L);
|
||||
return p;
|
||||
});
|
||||
|
||||
PairingStatusResponse result = pairingService.inviteUser(1L, "ABC123DEF456");
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
verify(pairingRelationRepository).save(any(PairingRelation.class));
|
||||
verify(fcmService).sendToToken(eq("user-fcm-token"), anyString(), anyString(), anyMap());
|
||||
verify(activityLogService).createLog(eq(guardian), any(), anyString(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - Guardian sudah ACTIVE pairing harus throw PairingException")
|
||||
void inviteUser_alreadyActivePairing_shouldThrow() {
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(true);
|
||||
|
||||
assertThatThrownBy(() -> pairingService.inviteUser(1L, "ABC123DEF456"))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("sudah memiliki user yang dipair");
|
||||
|
||||
verify(pairingRelationRepository, never()).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - Guardian sudah PENDING invite harus throw PairingException")
|
||||
void inviteUser_alreadyPendingInvite_shouldThrow() {
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.PENDING)).thenReturn(true);
|
||||
|
||||
assertThatThrownBy(() -> pairingService.inviteUser(1L, "ABC123DEF456"))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("sudah punya invite yang menunggu");
|
||||
|
||||
verify(pairingRelationRepository, never()).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - uniqueUserId tidak ditemukan harus throw ResourceNotFoundException")
|
||||
void inviteUser_userNotFound_shouldThrow() {
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.PENDING)).thenReturn(false);
|
||||
when(userRepository.findById(1L)).thenReturn(Optional.of(guardian));
|
||||
when(userRepository.findByUniqueUserId("INVALID")).thenReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> pairingService.inviteUser(1L, "INVALID"))
|
||||
.isInstanceOf(ResourceNotFoundException.class)
|
||||
.hasMessageContaining("tidak ditemukan");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - target bukan ROLE_USER harus throw PairingException")
|
||||
void inviteUser_targetNotUser_shouldThrow() {
|
||||
User anotherGuardian = User.builder()
|
||||
.id(3L).role("ROLE_GUARDIAN").uniqueUserId("GRD000000001").build();
|
||||
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.PENDING)).thenReturn(false);
|
||||
when(userRepository.findById(1L)).thenReturn(Optional.of(guardian));
|
||||
when(userRepository.findByUniqueUserId("GRD000000001")).thenReturn(Optional.of(anotherGuardian));
|
||||
|
||||
assertThatThrownBy(() -> pairingService.inviteUser(1L, "GRD000000001"))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("bukan milik User");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("inviteUser - User sudah ACTIVE dengan Guardian lain harus throw PairingException")
|
||||
void inviteUser_userAlreadyPaired_shouldThrow() {
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE)).thenReturn(false);
|
||||
when(pairingRelationRepository.existsByGuardian_IdAndStatus(1L, PairingStatus.PENDING)).thenReturn(false);
|
||||
when(userRepository.findById(1L)).thenReturn(Optional.of(guardian));
|
||||
when(userRepository.findByUniqueUserId("ABC123DEF456")).thenReturn(Optional.of(user));
|
||||
when(pairingRelationRepository.existsByUser_IdAndStatus(2L, PairingStatus.ACTIVE)).thenReturn(true);
|
||||
|
||||
assertThatThrownBy(() -> pairingService.inviteUser(1L, "ABC123DEF456"))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("sudah dipair dengan Guardian lain");
|
||||
}
|
||||
|
||||
// ===== RESPOND TO PAIRING TESTS =====
|
||||
|
||||
@Test
|
||||
@DisplayName("respondToPairing - accept: status harus jadi ACTIVE")
|
||||
void respondToPairing_accept_shouldSetStatusActive() {
|
||||
PairingRelation pairing = PairingRelation.builder()
|
||||
.id(10L).guardian(guardian).user(user).status(PairingStatus.PENDING).build();
|
||||
|
||||
when(pairingRelationRepository.findById(10L)).thenReturn(Optional.of(pairing));
|
||||
when(pairingRelationRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
// Stub untuk pembuatan config saat accept
|
||||
when(voiceCommandConfigRepository.existsByUserId(2L)).thenReturn(false);
|
||||
when(hardwareShortcutRepository.existsByUserId(2L)).thenReturn(false);
|
||||
when(aiConfigRepository.findByUserId(2L)).thenReturn(Optional.empty());
|
||||
when(aiConfigRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
|
||||
PairingStatusResponse result = pairingService.respondToPairing(2L, 10L, true);
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(pairing.getStatus()).isEqualTo(PairingStatus.ACTIVE);
|
||||
verify(pairingRelationRepository).save(pairing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("respondToPairing - reject: status harus jadi REJECTED")
|
||||
void respondToPairing_reject_shouldSetStatusRejected() {
|
||||
PairingRelation pairing = PairingRelation.builder()
|
||||
.id(10L).guardian(guardian).user(user).status(PairingStatus.PENDING).build();
|
||||
|
||||
when(pairingRelationRepository.findById(10L)).thenReturn(Optional.of(pairing));
|
||||
when(pairingRelationRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
|
||||
PairingStatusResponse result = pairingService.respondToPairing(2L, 10L, false);
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(pairing.getStatus()).isEqualTo(PairingStatus.REJECTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("respondToPairing - user yang salah harus throw PairingException")
|
||||
void respondToPairing_wrongUser_shouldThrow() {
|
||||
PairingRelation pairing = PairingRelation.builder()
|
||||
.id(10L).guardian(guardian).user(user).status(PairingStatus.PENDING).build();
|
||||
|
||||
when(pairingRelationRepository.findById(10L)).thenReturn(Optional.of(pairing));
|
||||
|
||||
// userId=99 bukan pemilik pairing ini (user.id=2)
|
||||
assertThatThrownBy(() -> pairingService.respondToPairing(99L, 10L, true))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("tidak berhak");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("respondToPairing - pairing yang sudah direspons harus throw PairingException")
|
||||
void respondToPairing_alreadyResponded_shouldThrow() {
|
||||
PairingRelation pairing = PairingRelation.builder()
|
||||
.id(10L).guardian(guardian).user(user).status(PairingStatus.ACTIVE).build();
|
||||
|
||||
when(pairingRelationRepository.findById(10L)).thenReturn(Optional.of(pairing));
|
||||
|
||||
assertThatThrownBy(() -> pairingService.respondToPairing(2L, 10L, true))
|
||||
.isInstanceOf(PairingException.class)
|
||||
.hasMessageContaining("sudah direspons");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user