test: add ActivityLogServiceTest unit test

This commit is contained in:
5803024019 2026-05-15 21:46:04 +07:00
parent 42543c27df
commit 2c5626c0f9

View File

@ -0,0 +1,196 @@
package com.walkguide.service;
import com.walkguide.dto.response.ActivityLogResponse;
import com.walkguide.entity.ActivityLog;
import com.walkguide.entity.PairingRelation;
import com.walkguide.entity.User;
import com.walkguide.enums.ActivityLogType;
import com.walkguide.enums.PairingStatus;
import com.walkguide.exception.ResourceNotFoundException;
import com.walkguide.repository.ActivityLogRepository;
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 org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import java.time.LocalDateTime;
import java.util.List;
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("ActivityLogService Unit Tests")
class ActivityLogServiceTest {
@Mock ActivityLogRepository activityLogRepository;
@Mock PairingRelationRepository pairingRelationRepository;
@InjectMocks ActivityLogService activityLogService;
private User sampleUser;
private User sampleGuardian;
private ActivityLog sampleLog;
@BeforeEach
void setUp() {
sampleUser = User.builder()
.id(1L).email("user@test.com").role("ROLE_USER")
.displayName("Test User").build();
sampleGuardian = User.builder()
.id(2L).email("guardian@test.com").role("ROLE_GUARDIAN")
.displayName("Test Guardian").build();
sampleLog = ActivityLog.builder()
.id(10L).user(sampleUser)
.logType(ActivityLogType.LOGIN)
.description("User login")
.metadata(null)
.build();
}
// ===== CREATE LOG TESTS =====
@Test
@DisplayName("createLog - harus simpan ActivityLog dengan data yang benar")
void createLog_shouldSaveWithCorrectData() {
activityLogService.createLog(sampleUser, ActivityLogType.LOGIN, "User login", null);
ArgumentCaptor<ActivityLog> captor = ArgumentCaptor.forClass(ActivityLog.class);
verify(activityLogRepository).save(captor.capture());
ActivityLog saved = captor.getValue();
assertThat(saved.getUser()).isEqualTo(sampleUser);
assertThat(saved.getLogType()).isEqualTo(ActivityLogType.LOGIN);
assertThat(saved.getDescription()).isEqualTo("User login");
assertThat(saved.getMetadata()).isNull();
}
@Test
@DisplayName("createLog - harus simpan ActivityLog dengan metadata")
void createLog_withMetadata_shouldSaveMetadata() {
String meta = "{\"label\":\"person\",\"direction\":\"LEFT\"}";
activityLogService.createLog(sampleUser, ActivityLogType.OBSTACLE_DETECTED, "Obstacle terdeteksi", meta);
ArgumentCaptor<ActivityLog> captor = ArgumentCaptor.forClass(ActivityLog.class);
verify(activityLogRepository).save(captor.capture());
assertThat(captor.getValue().getMetadata()).isEqualTo(meta);
assertThat(captor.getValue().getLogType()).isEqualTo(ActivityLogType.OBSTACLE_DETECTED);
}
@Test
@DisplayName("createLog - berbagai tipe log harus disimpan dengan benar")
void createLog_variousLogTypes_shouldSaveCorrectly() {
ActivityLogType[] types = {
ActivityLogType.LOGOUT, ActivityLogType.SOS_TRIGGERED,
ActivityLogType.GEOFENCE_EXIT, ActivityLogType.PAIRING_ACCEPTED
};
for (ActivityLogType type : types) {
activityLogService.createLog(sampleUser, type, "Deskripsi", null);
}
verify(activityLogRepository, times(types.length)).save(any(ActivityLog.class));
}
// ===== GET LOGS TESTS =====
@Test
@DisplayName("getLogs - harus return halaman log berdasarkan userId")
void getLogs_shouldReturnPagedLogs() {
sampleLog.setId(10L);
Page<ActivityLog> page = new PageImpl<>(List.of(sampleLog));
Pageable pageable = PageRequest.of(0, 10);
when(activityLogRepository.findByUser_IdOrderByCreatedAtDesc(1L, pageable))
.thenReturn(page);
Page<ActivityLogResponse> result = activityLogService.getLogs(1L, pageable);
assertThat(result.getTotalElements()).isEqualTo(1);
assertThat(result.getContent().get(0).getId()).isEqualTo(10L);
assertThat(result.getContent().get(0).getLogType()).isEqualTo("LOGIN");
assertThat(result.getContent().get(0).getDescription()).isEqualTo("User login");
}
@Test
@DisplayName("getLogs - tidak ada log harus return halaman kosong")
void getLogs_noLogs_shouldReturnEmptyPage() {
Pageable pageable = PageRequest.of(0, 10);
when(activityLogRepository.findByUser_IdOrderByCreatedAtDesc(1L, pageable))
.thenReturn(Page.empty());
Page<ActivityLogResponse> result = activityLogService.getLogs(1L, pageable);
assertThat(result.getTotalElements()).isZero();
assertThat(result.getContent()).isEmpty();
}
// ===== GET LOGS FOR GUARDIAN TESTS =====
@Test
@DisplayName("getLogsForGuardian - Guardian dengan pairing aktif harus return log user")
void getLogsForGuardian_activePairing_shouldReturnUserLogs() {
PairingRelation pairing = PairingRelation.builder()
.id(5L).guardian(sampleGuardian).user(sampleUser)
.status(PairingStatus.ACTIVE).build();
sampleLog.setId(10L);
Page<ActivityLog> page = new PageImpl<>(List.of(sampleLog));
Pageable pageable = PageRequest.of(0, 5);
when(pairingRelationRepository.findByGuardian_IdAndStatus(2L, PairingStatus.ACTIVE))
.thenReturn(Optional.of(pairing));
when(activityLogRepository.findByUser_IdOrderByCreatedAtDesc(1L, pageable))
.thenReturn(page);
Page<ActivityLogResponse> result = activityLogService.getLogsForGuardian(2L, pageable);
assertThat(result.getTotalElements()).isEqualTo(1);
assertThat(result.getContent().get(0).getLogType()).isEqualTo("LOGIN");
}
@Test
@DisplayName("getLogsForGuardian - Guardian tanpa pairing aktif harus throw ResourceNotFoundException")
void getLogsForGuardian_noPairing_shouldThrow() {
when(pairingRelationRepository.findByGuardian_IdAndStatus(2L, PairingStatus.ACTIVE))
.thenReturn(Optional.empty());
assertThatThrownBy(() -> activityLogService.getLogsForGuardian(2L, PageRequest.of(0, 10)))
.isInstanceOf(ResourceNotFoundException.class)
.hasMessageContaining("Belum ada user yang dipair");
verify(activityLogRepository, never()).findByUser_IdOrderByCreatedAtDesc(any(), any());
}
@Test
@DisplayName("getLogsForGuardian - paginasi multi-halaman harus diteruskan ke repository")
void getLogsForGuardian_pagination_shouldPassPageableToRepository() {
PairingRelation pairing = PairingRelation.builder()
.id(5L).guardian(sampleGuardian).user(sampleUser)
.status(PairingStatus.ACTIVE).build();
Pageable page2 = PageRequest.of(1, 10);
when(pairingRelationRepository.findByGuardian_IdAndStatus(2L, PairingStatus.ACTIVE))
.thenReturn(Optional.of(pairing));
when(activityLogRepository.findByUser_IdOrderByCreatedAtDesc(1L, page2))
.thenReturn(Page.empty());
activityLogService.getLogsForGuardian(2L, page2);
verify(activityLogRepository).findByUser_IdOrderByCreatedAtDesc(1L, page2);
}
}