test: add GeofenceServiceTest unit test

This commit is contained in:
5803024019 2026-05-15 21:56:28 +07:00
parent 688a3aac7c
commit 2966eda8c7

View File

@ -0,0 +1,184 @@
package com.walkguide.service;
import com.walkguide.dto.request.GeofenceConfigRequest;
import com.walkguide.dto.response.GeofenceResponse;
import com.walkguide.entity.GeofenceConfig;
import com.walkguide.entity.PairingRelation;
import com.walkguide.entity.User;
import com.walkguide.enums.PairingStatus;
import com.walkguide.exception.PairingException;
import com.walkguide.repository.GeofenceConfigRepository;
import com.walkguide.repository.PairingRelationRepository;
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.ArgumentCaptor;
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("GeofenceService Unit Tests")
class GeofenceServiceTest {
@Mock GeofenceConfigRepository geofenceConfigRepository;
@Mock PairingRelationRepository pairingRelationRepository;
@InjectMocks GeofenceService geofenceService;
private User guardian;
private User user;
private PairingRelation activePairing;
private GeofenceConfig existingConfig;
@BeforeEach
void setUp() {
guardian = User.builder().id(1L).email("guardian@test.com").displayName("Guardian Test").build();
user = User.builder().id(2L).email("user@test.com").displayName("User Test").build();
activePairing = PairingRelation.builder()
.id(1L)
.guardian(guardian)
.user(user)
.status(PairingStatus.ACTIVE)
.build();
existingConfig = GeofenceConfig.builder()
.id(10L)
.userId(2L)
.guardianId(1L)
.centerLat(-7.257)
.centerLng(112.752)
.radiusMeters(300.0)
.enabled(true)
.build();
}
// ===== getConfig TESTS =====
@Test
@DisplayName("getConfig - konfigurasi ada: harus return data dari repository")
void getConfig_configExists_shouldReturnExistingConfig() {
when(geofenceConfigRepository.findByUserId(2L)).thenReturn(Optional.of(existingConfig));
GeofenceResponse result = geofenceService.getConfig(2L);
assertThat(result).isNotNull();
assertThat(result.getId()).isEqualTo(10L);
assertThat(result.getCenterLat()).isEqualTo(-7.257);
assertThat(result.getCenterLng()).isEqualTo(112.752);
assertThat(result.getRadiusMeters()).isEqualTo(300.0);
assertThat(result.getEnabled()).isTrue();
}
@Test
@DisplayName("getConfig - konfigurasi tidak ada: harus return default (disabled, radius 500m)")
void getConfig_configNotFound_shouldReturnDefaultResponse() {
when(geofenceConfigRepository.findByUserId(99L)).thenReturn(Optional.empty());
GeofenceResponse result = geofenceService.getConfig(99L);
assertThat(result).isNotNull();
assertThat(result.getEnabled()).isFalse();
assertThat(result.getRadiusMeters()).isEqualTo(500.0);
assertThat(result.getId()).isNull();
}
// ===== updateConfig TESTS =====
@Test
@DisplayName("updateConfig - pairing aktif, config sudah ada: harus update field yang diberikan saja")
void updateConfig_activePairingAndConfigExists_shouldUpdateFields() {
GeofenceConfigRequest req = new GeofenceConfigRequest();
req.setCenterLat(-7.300);
req.setCenterLng(112.800);
req.setRadiusMeters(400.0);
req.setEnabled(true);
when(pairingRelationRepository.findByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE))
.thenReturn(Optional.of(activePairing));
when(geofenceConfigRepository.findByUserId(2L)).thenReturn(Optional.of(existingConfig));
when(geofenceConfigRepository.save(any(GeofenceConfig.class))).thenAnswer(inv -> inv.getArgument(0));
GeofenceResponse result = geofenceService.updateConfig(1L, req);
assertThat(result).isNotNull();
assertThat(result.getCenterLat()).isEqualTo(-7.300);
assertThat(result.getCenterLng()).isEqualTo(112.800);
assertThat(result.getRadiusMeters()).isEqualTo(400.0);
assertThat(result.getEnabled()).isTrue();
verify(geofenceConfigRepository).save(any(GeofenceConfig.class));
}
@Test
@DisplayName("updateConfig - config belum ada: harus buat config baru dengan userId dari pairing")
void updateConfig_configNotExists_shouldCreateNewConfig() {
GeofenceConfigRequest req = new GeofenceConfigRequest();
req.setCenterLat(-7.100);
req.setCenterLng(112.600);
req.setRadiusMeters(200.0);
req.setEnabled(false);
when(pairingRelationRepository.findByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE))
.thenReturn(Optional.of(activePairing));
when(geofenceConfigRepository.findByUserId(2L)).thenReturn(Optional.empty());
when(geofenceConfigRepository.save(any(GeofenceConfig.class))).thenAnswer(inv -> {
GeofenceConfig saved = inv.getArgument(0);
saved.setId(20L);
return saved;
});
GeofenceResponse result = geofenceService.updateConfig(1L, req);
ArgumentCaptor<GeofenceConfig> captor = ArgumentCaptor.forClass(GeofenceConfig.class);
verify(geofenceConfigRepository).save(captor.capture());
GeofenceConfig saved = captor.getValue();
assertThat(saved.getUserId()).isEqualTo(2L);
assertThat(saved.getGuardianId()).isEqualTo(1L);
assertThat(result.getCenterLat()).isEqualTo(-7.100);
assertThat(result.getEnabled()).isFalse();
}
@Test
@DisplayName("updateConfig - request field null: harus tidak menimpa nilai yang sudah ada")
void updateConfig_partialRequest_shouldNotOverwriteNullFields() {
GeofenceConfigRequest req = new GeofenceConfigRequest();
req.setEnabled(false); // hanya ubah enabled, field lain null
when(pairingRelationRepository.findByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE))
.thenReturn(Optional.of(activePairing));
when(geofenceConfigRepository.findByUserId(2L)).thenReturn(Optional.of(existingConfig));
when(geofenceConfigRepository.save(any(GeofenceConfig.class))).thenAnswer(inv -> inv.getArgument(0));
GeofenceResponse result = geofenceService.updateConfig(1L, req);
// centerLat, centerLng, radiusMeters tidak berubah
assertThat(result.getCenterLat()).isEqualTo(-7.257);
assertThat(result.getCenterLng()).isEqualTo(112.752);
assertThat(result.getRadiusMeters()).isEqualTo(300.0);
assertThat(result.getEnabled()).isFalse();
}
@Test
@DisplayName("updateConfig - tidak ada pairing aktif: harus throw PairingException")
void updateConfig_noActivePairing_shouldThrowPairingException() {
GeofenceConfigRequest req = new GeofenceConfigRequest();
req.setEnabled(true);
when(pairingRelationRepository.findByGuardian_IdAndStatus(1L, PairingStatus.ACTIVE))
.thenReturn(Optional.empty());
assertThatThrownBy(() -> geofenceService.updateConfig(1L, req))
.isInstanceOf(PairingException.class)
.hasMessageContaining("Tidak ada user yang dipair");
verify(geofenceConfigRepository, never()).save(any());
}
}