From 517ea9d7038b8705279df9001456762cf332fce0 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 13:16:32 +0530 Subject: [PATCH 01/19] [MOSIP-42804] - Sonar coverage added Signed-off-by: Nidhi0201 --- .../utils/SyncMasterDataServiceHelper.java | 5 + .../SyncMasterDataServiceHelperTest.java | 1148 ++++++++++++++++- .../impl/SyncAuthTokenServiceImplTest.java | 263 ++++ .../impl/SyncMasterDataServiceImplTest.java | 360 ++++++ .../impl/SyncRolesServiceImplTest.java | 110 ++ .../impl/SyncUserDetailsServiceImplTest.java | 278 ++++ 6 files changed, 2163 insertions(+), 1 deletion(-) create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncRolesServiceImplTest.java create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncUserDetailsServiceImplTest.java diff --git a/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java b/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java index 797326e8523..aeaf2973e88 100644 --- a/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java +++ b/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java @@ -2,6 +2,11 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import io.mosip.kernel.clientcrypto.constant.ClientType; import io.mosip.kernel.clientcrypto.dto.TpmCryptoRequestDto; import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java index 46a3af791c3..bc91ab8cd68 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java @@ -1,6 +1,16 @@ package io.mosip.kernel.syncdata.test.service; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.mosip.kernel.core.exception.ServiceError; +import io.mosip.kernel.syncdata.entity.id.HolidayID; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.syncdata.exception.SyncServiceException; +import org.mockito.InjectMocks; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import io.mosip.kernel.clientcrypto.constant.ClientType; import io.mosip.kernel.core.exception.FileNotFoundException; import io.mosip.kernel.core.http.ResponseWrapper; @@ -34,6 +44,7 @@ import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.client.RestTemplate; +import io.mosip.kernel.core.exception.ExceptionUtils; import java.time.LocalDate; import java.time.LocalDateTime; @@ -42,9 +53,13 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import static org.junit.Assert.*; -import static org.mockito.Mockito.lenient; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; @@ -58,6 +73,11 @@ public class SyncMasterDataServiceHelperTest { @Mock private SyncMasterDataServiceHelper syncMasterDataServiceHelper; + @InjectMocks + private SyncMasterDataServiceHelper syncMasterData; + + private SyncMasterDataServiceHelper realHelper; + @Mock private AppAuthenticationMethodRepository appAuthenticationMethodRepository; @@ -210,6 +230,21 @@ public void setUp() { locationHierarchyDto.setIsDeleted(false); locations.add(locationHierarchyDto); locationHierarchyLevelResponseDto.setLocationHierarchyLevels(locations); + + realHelper = new SyncMasterDataServiceHelper(); + ReflectionTestUtils.setField(realHelper, "documentTypeRepository", documentTypeRepository); + ObjectMapper realObjectMapper = new ObjectMapper(); + ReflectionTestUtils.setField(realHelper, "objectMapper", realObjectMapper); + ReflectionTestUtils.setField(realHelper, "locationHirerarchyUrl", "http://localhost/location-hierarchy"); + ReflectionTestUtils.setField(realHelper, "machineRepository", machineRepository); + ReflectionTestUtils.setField(realHelper, "registrationCenterRepository", registrationCenterRepository); + ReflectionTestUtils.setField(realHelper, "templateRepository", templateRepository); + ReflectionTestUtils.setField(realHelper, "templateFileFormatRepository", templateFileFormatRepository); + ReflectionTestUtils.setField(realHelper, "reasonCategoryRepository", reasonCategoryRepository); + ReflectionTestUtils.setField(realHelper, "reasonListRepository", reasonListRepository); + ReflectionTestUtils.setField(realHelper, "holidayRepository", holidayRepository); + ReflectionTestUtils.setField(realHelper, "blocklistedWordsRepository", blocklistedWordsRepository); + ReflectionTestUtils.setField(realHelper, "locationRepository", locationRepository); } @Test @@ -2080,4 +2115,1115 @@ public void testGetClientType2() { assertEquals(ClientType.ANDROID, SyncMasterDataServiceHelper.getClientType(machine)); } + @Test + public void testGetMachines_NoChangesFound() throws Exception { + + // Arrange + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // This makes isChangesFound return false + + // Act + CompletableFuture> future = + syncMasterData.getMachines( + "1001", + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC), + null); + + List result = future.get(); + + // Assert + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetMachines_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + // Make isChangesFound return true + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + entityDtimes.setCreatedDateTime(now); + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + // Prepare entity + Machine machine = new Machine(); + machine.setId("M1"); + machine.setName("Machine1"); + machine.setIpAddress("192.168.1.1"); + machine.setPublicKey("pubKey"); + machine.setIsActive(true); + machine.setIsDeleted(false); + machine.setKeyIndex("1"); + machine.setLangCode("eng"); + machine.setMacAddress("AA:BB:CC"); + machine.setMachineSpecId("SPEC1"); + machine.setSerialNum("SER123"); + machine.setValidityDateTime(now.plusDays(10)); + machine.setRegCenterId("1001"); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenReturn(Collections.singletonList(machine)); + + CompletableFuture> future = + syncMasterData.getMachines("1001", lastUpdated, now, null); + + List result = future.get(); + + assertEquals(1, result.size()); + + MachineDto dto = result.get(0); + + assertEquals("M1", dto.getId()); + assertEquals("Machine1", dto.getName()); + assertEquals("192.168.1.1", dto.getIpAddress()); + assertEquals("pubKey", dto.getPublicKey()); + assertEquals("1001", dto.getRegCenterId()); + } + + @Test + public void testGetMachines_EmptyRepositoryResult() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(5); + + EntityDtimes entityDtimes = + new EntityDtimes(null, now, null); + entityDtimes.setUpdatedDateTime(now); + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getMachines("1001", lastUpdated, now, null); + + List result = future.get(); + + assertTrue(result.isEmpty()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetMachines_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + // deletedDateTime is after lastUpdated → changes found + EntityDtimes entityDtimes = + new EntityDtimes(null, null, now); + + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getMachines("1001", lastUpdated, now, null) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetLocationHierarchyList_Success() throws Exception { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", + "http://localhost/location"); + LocalDateTime lastUpdated = LocalDateTime.now(ZoneOffset.UTC); + + // Prepare response DTO + LocationHierarchyDto dto = new LocationHierarchyDto(); + dto.setHierarchyLevel((short)1); + dto.setHierarchyLevelName("Country"); + + LocationHierarchyLevelResponseDto responseDto = + new LocationHierarchyLevelResponseDto(); + responseDto.setLocationHierarchyLevels( + Collections.singletonList(dto)); + + ResponseWrapper wrapper = + new ResponseWrapper<>(); + wrapper.setResponse(responseDto); + + String json = "{}"; // actual content doesn't matter because ObjectMapper is mocked + + ResponseEntity responseEntity = + new ResponseEntity<>(json, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + when(objectMapper.readValue(anyString(), eq(ResponseWrapper.class))) + .thenReturn(wrapper); + + when(objectMapper.writeValueAsString(any())) + .thenReturn("{}"); + + when(objectMapper.readValue(anyString(), + eq(LocationHierarchyLevelResponseDto.class))) + .thenReturn(responseDto); + + CompletableFuture> future = + syncMasterData.getLocationHierarchyList(lastUpdated); + + List result = future.get(); + + assertEquals(1, result.size()); + assertEquals("Country", result.get(0).getHierarchyLevelName()); + } + +// @Test(expected = RuntimeException.class) +// public void testGetLocationHierarchyList_WhenRestTemplateFails() { +// +// when(restTemplate.getForEntity(any(), eq(String.class))) +// .thenThrow(new RuntimeException("Failure")); +// +// syncMasterData.getLocationHierarchyList(null); +// } + + @Test(expected = SyncServiceException.class) + public void testGetLocationHierarchyList_WithValidationErrors() { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", // EXACT field name + "http://localhost/test"); + String errorJson = "{\"errors\":[{\"errorCode\":\"100\",\"message\":\"error\"}]}"; + + + ResponseEntity responseEntity = + new ResponseEntity<>(errorJson, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + syncMasterData.getLocationHierarchyList(null); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetLocationHierarchyList_DeserializationFailure() throws Exception { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", // EXACT field name + "http://localhost/test"); + String jsonResponse = "{\"response\": {}}"; + + ResponseEntity responseEntity = + new ResponseEntity<>(jsonResponse, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + // Force exception inside try block + when(objectMapper.readValue(anyString(), eq(ResponseWrapper.class))) + .thenThrow(new RuntimeException("JSON parsing failed")); + + syncMasterData.getLocationHierarchyList(null); + } + + @Test + public void testGetLocationHierarchyList() throws Exception { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", // EXACT field name + "http://localhost/test"); + String jsonResponse = "{\"response\":{}}"; + + ResponseEntity responseEntity = + new ResponseEntity<>(jsonResponse, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + // No validation errors (assuming empty list returned naturally) + + ResponseWrapper wrapper = new ResponseWrapper(); + wrapper.setResponse(new Object()); + + LocationHierarchyLevelResponseDto dto = + new LocationHierarchyLevelResponseDto(); + + List list = new ArrayList<>(); + list.add(new LocationHierarchyDto()); + dto.setLocationHierarchyLevels(list); + + when(objectMapper.readValue(anyString(), eq(ResponseWrapper.class))) + .thenReturn(wrapper); + + when(objectMapper.writeValueAsString(any())) + .thenReturn("{}"); + + when(objectMapper.readValue(anyString(), + eq(LocationHierarchyLevelResponseDto.class))) + .thenReturn(dto); + + CompletableFuture> result = + syncMasterData.getLocationHierarchyList(null, restTemplate); + + assertNotNull(result); + assertEquals(1, result.get().size()); + } + + @Test(expected = SyncServiceException.class) + public void testGetLocationHierarchyList_ValidationErrors() { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", // EXACT field name + "http://localhost/test"); + String errorJson = "{\"errors\":[{\"errorCode\":\"100\",\"message\":\"error\"}]}"; + + ResponseEntity responseEntity = + new ResponseEntity<>(errorJson, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + syncMasterData.getLocationHierarchyList(null, restTemplate); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetLocationHierarchyList_ShouldEnterCatchBlock() throws Exception { + + ReflectionTestUtils.setField(syncMasterData, + "locationHirerarchyUrl", // EXACT field name + "http://localhost/test"); + String jsonResponse = "{\"response\":{}}"; + + ResponseEntity responseEntity = + new ResponseEntity<>(jsonResponse, HttpStatus.OK); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(responseEntity); + + when(objectMapper.readValue(anyString(), eq(ResponseWrapper.class))) + .thenThrow(new RuntimeException("JSON parse error")); + + syncMasterData.getLocationHierarchyList(null, restTemplate); + } + + @Test + public void testGetRegistrationCenter_LastUpdatedNull_ShouldProceed() throws Exception { + + // repository for actual data fetch + when(registrationCenterRepository.findRegistrationCentersById( + anyString(), any(), any())) + .thenReturn(new ArrayList<>()); + + CompletableFuture> result = + syncMasterData.getRegistrationCenter( + "C1", + null, + LocalDateTime.now()); + + // Since repo returns empty list -> converter returns null + assertNull(result.get()); + } + + @Test + public void testGetRegistrationCenter_NoDataInTable_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + + // Mock delta table max dates = null + when(registrationCenterRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); + + CompletableFuture> result = + syncMasterData.getRegistrationCenter( + "C1", + lastUpdated, + LocalDateTime.now()); + + // isChangesFound returns false → method returns completedFuture(null) + assertNull(result.get()); + } + + @Test + public void testGetRegistrationCenter_ChangesFound_ShouldFetchData() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(5); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), // createdDateTime + null, + null + ); + + when(registrationCenterRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + RegistrationCenter entity = new RegistrationCenter(); + entity.setId("C1"); + + List list = new ArrayList<>(); + list.add(entity); + + when(registrationCenterRepository.findRegistrationCentersById( + anyString(), any(), any())) + .thenReturn(list); + + CompletableFuture> result = + syncMasterData.getRegistrationCenter( + "C1", + lastUpdated, + LocalDateTime.now()); + + assertNotNull(result.get()); + assertEquals(1, result.get().size()); + } + + @Test + public void testGetRegistrationCenter_NoChanges_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + lastUpdated.minusDays(2), + null, + null + ); + + when(registrationCenterRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + CompletableFuture> result = + syncMasterData.getRegistrationCenter( + "C1", + lastUpdated, + LocalDateTime.now()); + + assertNull(result.get()); + } + + @Test + public void testGetTemplates_NoChangesFound_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + // Mock repository used inside isChangesFound() + when(templateRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // result == null → isChangesFound() returns false + + CompletableFuture> future = + syncMasterData.getTemplates("REG", lastUpdated, currentTime); + + List result = future.get(); + + assertNull(result); + + // Ensure actual fetch method is NOT called + verify(templateRepository, never()) + .findAllLatestCreatedUpdateDeletedByModule(any(), any(), any()); + } + + @Test + public void testGetTemplates_WithChanges_ShouldReturnTemplateList() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(templateRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + Template template = new Template(); + template.setId("1"); + template.setName("TestTemplate"); + template.setDescription("Desc"); + template.setFileFormatCode("PDF"); + template.setModel("model"); + template.setFileText("text"); + template.setModuleId("REG"); + template.setModuleName("Registration"); + template.setTemplateTypeCode("TYPE1"); + template.setIsActive(true); + template.setIsDeleted(false); + template.setLangCode("eng"); + + when(templateRepository.findAllLatestCreatedUpdateDeletedByModule( + any(), any(), any())) + .thenReturn(List.of(template)); + + CompletableFuture> future = + syncMasterData.getTemplates("REG", lastUpdated, currentTime); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("1", result.get(0).getId()); + } + + @Test + public void testGetTemplates_LastUpdatedNull_ShouldSetEpoch() throws Exception { + + LocalDateTime currentTime = LocalDateTime.now(); + + Template template = new Template(); + template.setId("1"); + + when(templateRepository.findAllLatestCreatedUpdateDeletedByModule( + any(), any(), any())) + .thenReturn(List.of(template)); + + CompletableFuture> future = + syncMasterData.getTemplates("REG", null, currentTime); + + List result = future.get(); + + assertNotNull(result); + verify(templateRepository) + .findAllLatestCreatedUpdateDeletedByModule(any(), any(), eq("REG")); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetTemplates_DataAccessException_ShouldThrowSyncDataServiceException() { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(templateRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(templateRepository.findAllLatestCreatedUpdateDeletedByModule( + any(), any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getTemplates("REG", lastUpdated, currentTime); + } + + @Test + public void testGetTemplateFileFormats_NoChangesFound_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + when(templateFileFormatRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // isChangesFound() returns false + + CompletableFuture> future = + syncMasterData.getTemplateFileFormats(lastUpdated, currentTime); + + List result = future.get(); + + assertNull(result); + + verify(templateFileFormatRepository, never()) + .findAllLatestCreatedUpdateDeleted(any(), any()); + } + + @Test + public void testGetTemplateFileFormats_WithChanges_ShouldReturnList() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(templateFileFormatRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + TemplateFileFormat entity = new TemplateFileFormat(); + entity.setCode("PDF"); + entity.setDescription("PDF Format"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(templateFileFormatRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + CompletableFuture> future = + syncMasterData.getTemplateFileFormats(lastUpdated, currentTime); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("PDF", result.get(0).getCode()); + } + + @Test + public void testGetTemplateFileFormats_LastUpdatedNull_ShouldSetEpoch() throws Exception { + + LocalDateTime currentTime = LocalDateTime.now(); + + TemplateFileFormat entity = new TemplateFileFormat(); + entity.setCode("DOC"); + + when(templateFileFormatRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + CompletableFuture> future = + syncMasterData.getTemplateFileFormats(null, currentTime); + + List result = future.get(); + + assertNotNull(result); + + verify(templateFileFormatRepository) + .findAllLatestCreatedUpdateDeleted(any(), eq(currentTime)); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetTemplateFileFormats_DataAccessException_ShouldThrowException() { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(templateFileFormatRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(templateFileFormatRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getTemplateFileFormats(lastUpdated, currentTime); + } + + @Test + public void testGetReasonCategory_NoChangesFound_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + when(reasonCategoryRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getReasonCategory(lastUpdated, currentTime); + + assertNull(future.get()); + + verify(reasonCategoryRepository, never()) + .findAllLatestCreatedUpdateDeleted(any(), any()); + } + + @Test + public void testGetReasonCategory_WithChanges_ShouldReturnList() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(reasonCategoryRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + ReasonCategory entity = new ReasonCategory(); + entity.setCode("RC1"); + entity.setDescription("Reason Desc"); + entity.setName("Reason Name"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(reasonCategoryRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + CompletableFuture> future = + syncMasterData.getReasonCategory(lastUpdated, currentTime); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("RC1", result.get(0).getCode()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetReasonCategory_DataAccessException_ShouldThrowException() { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(reasonCategoryRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(reasonCategoryRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getReasonCategory(lastUpdated, currentTime); + } + + @Test + public void testGetReasonList_NoChangesFound_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + when(reasonListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // isChangesFound() returns false + + CompletableFuture> future = + syncMasterData.getReasonList(lastUpdated, currentTime); + + assertNull(future.get()); + + verify(reasonListRepository, never()) + .findAllLatestCreatedUpdateDeleted(any(), any()); + } + + @Test + public void testGetReasonList_WithChanges_ShouldReturnList() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(reasonListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + ReasonList entity = new ReasonList(); + entity.setCode("R001"); + entity.setName("Reason Name"); + entity.setDescription("Reason Desc"); + entity.setRsnCatCode("CAT1"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(reasonListRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + CompletableFuture> future = + syncMasterData.getReasonList(lastUpdated, currentTime); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("R001", result.get(0).getCode()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetReasonList_DataAccessException_ShouldThrowException() { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(reasonListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(reasonListRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getReasonList(lastUpdated, currentTime); + } + + @Test + public void testGetHolidays_NoChangesFound_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + when(holidayRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getHolidays(lastUpdated, "M1", currentTime); + + assertNull(future.get()); + + verify(holidayRepository, never()) + .findAllLatestCreatedUpdateDeletedByMachineId(any(), any(), any()); + } + + @Test + public void testGetHolidays_WithChanges_ShouldReturnList() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(holidayRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + // Prepare HolidayID + HolidayID holidayID = new HolidayID(); + holidayID.setHolidayDate(LocalDate.of(2025, 1, 26)); + holidayID.setHolidayName("Republic Day"); + holidayID.setLangCode("eng"); + holidayID.setLocationCode("LOC1"); + + Holiday holiday = new Holiday(); + holiday.setId(1); + holiday.setHolidayId(holidayID); + holiday.setIsActive(true); + holiday.setIsDeleted(false); + + when(holidayRepository.findAllLatestCreatedUpdateDeletedByMachineId( + any(), any(), any())) + .thenReturn(List.of(holiday)); + + CompletableFuture> future = + syncMasterData.getHolidays(lastUpdated, "M1", currentTime); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + HolidayDto dto = result.get(0); + assertEquals("Republic Day", dto.getHolidayName()); + assertEquals("2025", dto.getHolidayYear()); + } + + @Test + public void testGetHolidays_EmptyList_ShouldReturnNull() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(2); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(holidayRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(holidayRepository.findAllLatestCreatedUpdateDeletedByMachineId( + any(), any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getHolidays(lastUpdated, "M1", currentTime); + + assertNull(future.get()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetHolidays_DataAccessException_ShouldThrowException() { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); + LocalDateTime currentTime = LocalDateTime.now(); + + EntityDtimes entityDtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + + when(holidayRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(holidayRepository.findAllLatestCreatedUpdateDeletedByMachineId( + any(), any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getHolidays(lastUpdated, "M1", currentTime); + } + + @Test + public void testGetBlackListedWords_NoChangesFound_ShouldReturnNull() throws Exception { + + when(blocklistedWordsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getBlackListedWords( + LocalDateTime.now().minusDays(1), + LocalDateTime.now()); + + assertNull(future.get()); + + verify(blocklistedWordsRepository, never()) + .findAllLatestCreatedUpdateDeleted(any(), any()); + } + + @Test + public void testGetBlackListedWords_WithChanges_ShouldReturnList() throws Exception { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null); + + when(blocklistedWordsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + BlocklistedWords entity = new BlocklistedWords(); + entity.setWord("badword"); + entity.setDescription("desc"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(blocklistedWordsRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + List result = + syncMasterData.getBlackListedWords( + LocalDateTime.now().minusDays(2), + LocalDateTime.now()).get(); + + assertNotNull(result); + assertEquals("badword", result.get(0).getWord()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetBlackListedWords_DataAccessException() { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null); + + when(blocklistedWordsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + when(blocklistedWordsRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getBlackListedWords( + LocalDateTime.now().minusDays(1), + LocalDateTime.now()); + } + + @Test + public void testGetDocumentTypes_WithChanges_ShouldReturnList() throws Exception { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null); + + when(documentTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + DocumentType entity = new DocumentType(); + entity.setCode("DOC1"); + entity.setName("Passport"); + entity.setDescription("Passport Doc"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(documentTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + List result = + syncMasterData.getDocumentTypes( + LocalDateTime.now().minusDays(2), + LocalDateTime.now()).get(); + + assertEquals("DOC1", result.get(0).getCode()); + } + + @Test + public void testGetLocationHierarchy_WithChanges_ShouldReturnList() throws Exception { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null); + + when(locationRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + Location entity = new Location(); + entity.setCode("LOC1"); + entity.setName("Bihar"); + entity.setHierarchyLevel(1); + entity.setHierarchyName("State"); + entity.setParentLocCode(null); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(locationRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + List result = + syncMasterData.getLocationHierarchy( + LocalDateTime.now().minusDays(2), + LocalDateTime.now()).get(); + + assertEquals("LOC1", result.get(0).getCode()); + } + + @Test + public void testGetTemplateTypes_WithChanges_ShouldReturnList() throws Exception { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + LocalDateTime.now(), + null); + + when(templateTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + TemplateType entity = new TemplateType(); + entity.setCode("TT1"); + entity.setDescription("Template Type"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(templateTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + List result = + syncMasterData.getTemplateTypes( + LocalDateTime.now().minusDays(2), + LocalDateTime.now()).get(); + + assertEquals("TT1", result.get(0).getCode()); + } + + @Test + public void testGetDocumentTypes_LastUpdatedNull_ShouldFetch() throws Exception { + + DocumentType entity = new DocumentType(); + entity.setCode("DOC1"); + + when(documentTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(entity)); + + List result = + syncMasterData.getDocumentTypes(null, LocalDateTime.now()).get(); + + assertNotNull(result); + } + + @Test + public void testGetDocumentTypes_ResultNull_ShouldReturnNull() throws Exception { + + when(documentTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); + + List result = + syncMasterData.getDocumentTypes( + LocalDateTime.now().minusDays(1), + LocalDateTime.now()).get(); + + assertNull(result); + } + + @Test + public void testDeletedDateTimeCondition_ShouldFetch() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(5); + + EntityDtimes dtimes = new EntityDtimes( + null, + null, + LocalDateTime.now().minusDays(1) + ); + + when(documentTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + when(documentTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(new DocumentType())); + + List result = + syncMasterData.getDocumentTypes(lastUpdated, LocalDateTime.now()).get(); + + assertNotNull(result); + } + + @Test + public void testUpdatedDateTimeCondition_ShouldFetch() throws Exception { + + LocalDateTime lastUpdated = LocalDateTime.now().minusDays(5); + + EntityDtimes dtimes = new EntityDtimes( + null, + LocalDateTime.now().minusDays(1), + null + ); + + when(documentTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + when(documentTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(new DocumentType())); + + List result = + syncMasterData.getDocumentTypes(lastUpdated, LocalDateTime.now()).get(); + + assertNotNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testDataAccessException_ShouldThrowSyncDataServiceException() { + + EntityDtimes dtimes = new EntityDtimes( + LocalDateTime.now(), + null, + null + ); + + when(documentTypeRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(dtimes); + + when(documentTypeRepository.findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB Error")); + + syncMasterData.getDocumentTypes( + LocalDateTime.now().minusDays(1), + LocalDateTime.now()); + } + } diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java new file mode 100644 index 00000000000..db8e8e6fcfa --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java @@ -0,0 +1,263 @@ +package io.mosip.kernel.syncdata.test.service.impl; + +import com.auth0.jwt.impl.JWTParser; +import com.auth0.jwt.interfaces.Header; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.mosip.kernel.clientcrypto.exception.ClientCryptoException; +import io.mosip.kernel.clientcrypto.service.impl.ClientCryptoFacade; +import io.mosip.kernel.core.authmanager.model.AuthNResponse; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.cryptomanager.util.CryptomanagerUtils; +import io.mosip.kernel.syncdata.constant.SyncAuthErrorCode; +import io.mosip.kernel.syncdata.dto.MachineAuthDto; +import io.mosip.kernel.syncdata.dto.MachineOtpDto; +import io.mosip.kernel.syncdata.dto.response.TokenResponseDto; +import io.mosip.kernel.syncdata.entity.Machine; +import io.mosip.kernel.syncdata.exception.RequestException; +import io.mosip.kernel.syncdata.repository.MachineRepository; +import io.mosip.kernel.syncdata.service.SyncUserDetailsService; + +import io.mosip.kernel.syncdata.service.impl.SyncAuthTokenServiceImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.RestTemplate; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Base64; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SyncAuthTokenServiceImplTest { + + @InjectMocks + @Spy + private SyncAuthTokenServiceImpl service; + + @Mock private ClientCryptoFacade clientCryptoFacade; + @Mock private MachineRepository machineRepository; + @Mock private SyncUserDetailsService syncUserDetailsService; + @Mock private RestTemplate restTemplate; + @Mock private CryptomanagerUtils cryptomanagerUtils; + @Mock private ObjectMapper objectMapper; + + private Machine machine; + + @BeforeEach + void setup() { + machine = new Machine(); + machine.setId("1"); + machine.setName("machine1"); + machine.setPublicKey("cHVibGlj"); + machine.setSignPublicKey("c2lnbg=="); + machine.setSignKeyIndex("KEY1"); + machine.setIsActive(true); + + ReflectionTestUtils.setField(service, "minMinutes", 5); + ReflectionTestUtils.setField(service, "maxMinutes", -5); + ReflectionTestUtils.setField(service, "clientId", "cid"); + ReflectionTestUtils.setField(service, "secretKey", "secret"); + ReflectionTestUtils.setField(service, "authTokenInternalAppId", "appId"); + ReflectionTestUtils.setField(service, "newAuthTokenInternalUrl", "http://new"); + ReflectionTestUtils.setField(service, "otpAuthTokenInternalUrl", "http://otp"); + ReflectionTestUtils.setField(service, "refreshAuthTokenInternalUrl", "http://refresh"); + } + + // ===================================================== + // getAuthToken SUCCESS + // ===================================================== + // ======== HELPER TO CREATE JWT-LIKE TOKEN ======== + private String createToken(String kid, String machineName, LocalDateTime timestamp) throws Exception { + String headerJson = "{\"kid\":\"" + kid + "\"}"; + String payloadJson = "{\"machineName\":\"" + machineName + "\",\"timestamp\":\"" + timestamp + "\",\"authType\":\"NEW\"}"; + String signature = "sig"; + + return Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(signature.getBytes()); + } + + @Test + void getAuthToken_invalidRequest_throwsRequestException() { + // Invalid token with less than 3 parts + String invalidToken = "invalid.token"; + + RequestException ex = assertThrows(RequestException.class, + () -> service.getAuthToken(invalidToken)); + + // Verify exception code and message + assertEquals(SyncAuthErrorCode.INVALID_REQUEST.getErrorCode(), ex.getErrorCode()); + + } + + // ======================= SUCCESS ======================= + @Test + void getAuthToken_success_verifiedTrue() throws Exception { + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + // Create JWT-like token + String headerJson = "{\"kid\":\"KEY1\"}"; + String payloadJson = "{\"machineName\":\"machine1\",\"userId\":\"user1\",\"password\":\"pass123\",\"timestamp\":\"" + now + "\",\"authType\":\"NEW\"}"; + String token = Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString("sig".getBytes()); + + // 1️⃣ Mock machineRepository to return the machine (used in validateRequestData) + when(machineRepository.findBySignKeyIndex("KEY1")).thenReturn(List.of(machine)); + + // 2️⃣ Force validateSignature = true + when(clientCryptoFacade.validateSignature(any(), any(), any(), any())).thenReturn(true); + + // 3️⃣ Mock payload to MachineAuthDto + when(objectMapper.readValue(any(byte[].class), eq(MachineAuthDto.class))) + .thenReturn(new MachineAuthDto() {{ + setMachineName("machine1"); + setUserId("user1"); + setPassword("pass123"); + setAuthType("NEW"); + setTimestamp(now); + }}); + + // 4️⃣ Mock REST call inside getTokenResponseDTO + String fakeResponse = "{\"response\":{}}"; // minimal valid JSON + when(restTemplate.postForEntity(any(), any(), eq(String.class))) + .thenReturn(ResponseEntity.ok(fakeResponse)); + + // 5️⃣ Mock ObjectMapper.readValue to convert fake response + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(new TokenResponseDto()); + when(objectMapper.readValue(eq(fakeResponse), any(TypeReference.class))).thenReturn(wrapper); + + // 6️⃣ Mock encryption + when(cryptomanagerUtils.decodeBase64Data(anyString())).thenReturn("decoded".getBytes()); + + // Call public method + assertThrows(RequestException.class, () -> { + service.getAuthToken(token); + }); + + } + + // ===================================================== + // INVALID TOKEN FORMAT + // ===================================================== + + @Test + void getAuthToken_invalidFormat() { + assertThrows(RequestException.class, + () -> service.getAuthToken("invalid.token")); + } + + // ===================================================== + // TIMESTAMP VALIDATION + // ===================================================== + + @Test + void validateRequestTimestamp_invalid() { + + LocalDateTime oldTime = LocalDateTime.now(ZoneOffset.UTC).minusHours(2); + + assertThrows(RequestException.class, + () -> ReflectionTestUtils.invokeMethod(service, + "validateRequestTimestamp", oldTime)); + } + + // ===================================================== + // sendOTP SUCCESS + // ===================================================== + + @Test + void sendOTP_success() throws Exception { + + ReflectionTestUtils.setField(service, "sendOTPUrl", "http://otp"); + + String headerJson = "{\"kid\":\"KEY1\"}"; + String payloadJson = "{\"userId\":\"user1\",\"timestamp\":\"" + + LocalDateTime.now(ZoneOffset.UTC) + "\",\"otpChannel\":\"email\"}"; + + String token = Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString("sig".getBytes()); + + // ✅ Machine mock + when(machineRepository.findBySignKeyIndex("KEY1")) + .thenReturn(List.of(machine)); + + // ✅ decode base64 mock + when(cryptomanagerUtils.decodeBase64Data(anyString())) + .thenReturn("decoded".getBytes()); + + // ✅ signature validation + when(clientCryptoFacade.validateSignature(any(), any(), any(), any())) + .thenReturn(true); + + // ✅ MachineOtpDto + MachineOtpDto otpDto = new MachineOtpDto(); + otpDto.setTimestamp(LocalDateTime.now(ZoneOffset.UTC)); + otpDto.setUserId("user1"); + otpDto.setOtpChannel(Collections.singletonList("email")); + + when(objectMapper.readValue(any(byte[].class), eq(MachineOtpDto.class))) + .thenReturn(otpDto); + + // ✅ REST response + when(restTemplate.postForEntity(any(), any(), eq(String.class))) + .thenReturn(ResponseEntity.ok("{}")); + + // ✅ final wrapper parse + when(objectMapper.readValue(anyString(), + any(TypeReference.class))) + .thenReturn(new ResponseWrapper<>()); + + ResponseWrapper response = + service.sendOTP(token); + + assertNotNull(response); + } + + // ===================================================== + // getTokenResponseDTO NULL RESPONSE + // ===================================================== + + @Test + void getTokenResponseDTO_nullBranch() { + + MachineAuthDto dto = new MachineAuthDto(); + dto.setAuthType("UNKNOWN"); + + assertThrows(RequestException.class, + () -> ReflectionTestUtils.invokeMethod(service, + "getTokenResponseDTO", dto)); + } + + // ===================================================== + // SIGNATURE INVALID + // ===================================================== + + @Test + void validateRequestData_invalidSignature() { + + assertThrows(RequestException.class, + () -> ReflectionTestUtils.invokeMethod(service, + "validateRequestData", + "{}".getBytes(), + "{}".getBytes(), + "sig".getBytes())); + } +} diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java new file mode 100644 index 00000000000..5dcfe39253c --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java @@ -0,0 +1,360 @@ +package io.mosip.kernel.syncdata.test.service.impl; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; +import io.mosip.kernel.clientcrypto.service.spi.ClientCryptoManagerService; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.keymanagerservice.entity.CACertificateStore; +import io.mosip.kernel.syncdata.constant.MasterDataErrorCode; +import io.mosip.kernel.syncdata.dto.*; +import io.mosip.kernel.syncdata.dto.response.*; +import io.mosip.kernel.syncdata.entity.Machine; +import io.mosip.kernel.syncdata.exception.RequestException; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.keymanagerservice.repository.CACertificateStoreRepository; +import io.mosip.kernel.syncdata.repository.MachineRepository; +import io.mosip.kernel.syncdata.repository.ModuleDetailRepository; +import io.mosip.kernel.syncdata.service.helper.ClientSettingsHelper; +import io.mosip.kernel.syncdata.service.helper.IdentitySchemaHelper; +import io.mosip.kernel.syncdata.service.helper.KeymanagerHelper; +import io.mosip.kernel.syncdata.service.impl.SyncMasterDataServiceImpl; +import io.mosip.kernel.cryptomanager.util.CryptomanagerUtils; +import io.mosip.kernel.syncdata.utils.MapperUtils; +import io.mosip.kernel.syncdata.utils.SyncMasterDataServiceHelper; + +import org.junit.jupiter.api.BeforeEach; +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.core.env.Environment; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SyncMasterDataServiceImplTest { + + @InjectMocks + private SyncMasterDataServiceImpl service; + + @Mock private SyncMasterDataServiceHelper serviceHelper; + @Mock private MachineRepository machineRepo; + @Mock private MapperUtils mapper; + @Mock private IdentitySchemaHelper identitySchemaHelper; + @Mock private KeymanagerHelper keymanagerHelper; + @Mock private RestTemplate restTemplate; + @Mock private CACertificateStoreRepository caCertificateStoreRepository; + @Mock private ModuleDetailRepository moduleDetailRepository; + @Mock private ClientSettingsHelper clientSettingsHelper; + @Mock private Environment environment; + @Mock private CryptomanagerUtils cryptomanagerUtils; + @Mock private ClientCryptoManagerService clientCryptoManagerService; + @Mock private ObjectMapper objectMapper; + + private Machine machine; + + @BeforeEach + void setup() { + machine = new Machine(); + machine.setName("machine1"); + machine.setPublicKey("cHVibGlj"); // base64 + machine.setKeyIndex("KEY1"); + } + + // =============================== + // validateKeyMachineMapping + // =============================== + + @Test + void validateKeyMachineMapping_machineNotFound() { + when(machineRepo.findByMachineName(anyString())).thenReturn(Collections.emptyList()); + + UploadPublicKeyRequestDto dto = new UploadPublicKeyRequestDto(); + dto.setMachineName("machine1"); + + assertThrows(RequestException.class, + () -> service.validateKeyMachineMapping(dto)); + } + + @Test + void validateKeyMachineMapping_publicKeyEmpty() { + machine.setPublicKey(""); + when(machineRepo.findByMachineName(anyString())).thenReturn(List.of(machine)); + + UploadPublicKeyRequestDto dto = new UploadPublicKeyRequestDto(); + dto.setMachineName("machine1"); + + assertThrows(RequestException.class, + () -> service.validateKeyMachineMapping(dto)); + } + + @Test + void validateKeyMachineMapping_success() { + when(machineRepo.findByMachineName(anyString())).thenReturn(List.of(machine)); + when(cryptomanagerUtils.decodeBase64Data(anyString())) + .thenReturn("test".getBytes()); + + UploadPublicKeyRequestDto dto = new UploadPublicKeyRequestDto(); + dto.setMachineName("machine1"); + dto.setPublicKey("cHVibGlj"); + + UploadPublicKeyResponseDto response = + service.validateKeyMachineMapping(dto); + + assertEquals("KEY1", response.getKeyIndex()); + } + + // =============================== + // getClientPublicKey + // =============================== + + @Test + void getClientPublicKey_machineNotFound() { + assertThrows(SyncDataServiceException.class, + () -> service.getClientPublicKey("123")); + } + + // =============================== + // getPartnerCACertificates + // =============================== + + @Test + void getPartnerCACertificates_nullList() { + when(caCertificateStoreRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(null); + + CACertificates result = + service.getPartnerCACertificates(null, LocalDateTime.now()); + + assertNotNull(result); + assertTrue(result.getCertificateDTOList().isEmpty()); + } + + @Test + void getPartnerCACertificates_success() { + CACertificateStore cert = new CACertificateStore(); + cert.setCertId("1"); + cert.setCertIssuer("issuer"); + + when(caCertificateStoreRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(List.of(cert)); + + CACertificates result = + service.getPartnerCACertificates(LocalDateTime.now().minusDays(1), + LocalDateTime.now()); + + assertEquals(1, result.getCertificateDTOList().size()); + } + + // =============================== + // syncClientSettings + // =============================== + + @Test + void syncClientSettings_success() { + RegistrationCenterMachineDto dto = new RegistrationCenterMachineDto(); + dto.setMachineId("MID"); + dto.setRegCenterId("RID"); + + when(serviceHelper.getRegistrationCenterMachine(any(), any())) + .thenReturn(dto); + + Map futureMap = new HashMap<>(); + futureMap.put(String.class, CompletableFuture.completedFuture("data")); + + when(clientSettingsHelper.getInitiateDataFetch(any(), any(), any(), any(), + anyBoolean(), anyBoolean(), any())) + .thenReturn(futureMap); + + when(clientSettingsHelper.retrieveData(any(), any(), anyBoolean())) + .thenReturn(new ArrayList<>()); + + SyncDataResponseDto response = + service.syncClientSettings("RID", "KEY", + LocalDateTime.now(), LocalDateTime.now()); + + assertNotNull(response); + } + + // =============================== + // syncClientSettingsV2 + // =============================== + + @Test + void syncClientSettingsV2_success() { + RegistrationCenterMachineDto dto = new RegistrationCenterMachineDto(); + dto.setMachineId("MID"); + dto.setRegCenterId("RID"); + + when(serviceHelper.getRegistrationCenterMachine(any(), any())) + .thenReturn(dto); + + Map futureMap = new HashMap<>(); + futureMap.put(String.class, CompletableFuture.completedFuture("data")); + + when(clientSettingsHelper.getInitiateDataFetch(any(), any(), any(), any(), + anyBoolean(), anyBoolean(), any())) + .thenReturn(futureMap); + + when(clientSettingsHelper.retrieveData(any(), any(), anyBoolean())) + .thenReturn(new ArrayList<>()); + + when(clientSettingsHelper.getConfiguredScriptUrlDetail(any())) + .thenReturn(new ArrayList<>()); + + SyncDataResponseDto response = + service.syncClientSettingsV2("RID", "KEY", + LocalDateTime.now(), LocalDateTime.now(), + "1.0", "ALL"); + + assertNotNull(response); + } + + // =============================== + // getClientSettingsJsonFile + // =============================== + + @Test + void getClientSettingsJsonFile_machineNotFound() { + when(machineRepo.findByMachineKeyIndex(anyString())) + .thenReturn(Collections.emptyList()); + + assertThrows(RequestException.class, + () -> service.getClientSettingsJsonFile("file.json", "KEY")); + } + + @Test + void getClientSettingsJsonFile_notEncrypted() throws Exception { + + Machine machine = new Machine(); + machine.setPublicKey("PUBKEY"); + + when(machineRepo.findByMachineKeyIndex(anyString())) + .thenReturn(List.of(machine)); + + when(environment.getProperty(anyString(), eq(Boolean.class), eq(false))) + .thenReturn(false); + + // create temp file + Path tempFile = java.nio.file.Files.createTempFile("test", ".json"); + java.nio.file.Files.writeString(tempFile, "sample-data"); + + // inject directory path + org.springframework.test.util.ReflectionTestUtils + .setField(service, "clientSettingsDir", + tempFile.getParent().toString()); + + when(keymanagerHelper.getFileSignature(anyString())) + .thenReturn("SIGNATURE"); + + ResponseEntity response = + service.getClientSettingsJsonFile(tempFile.getFileName().toString(), "KEY"); + + assertEquals("sample-data", response.getBody()); + } + + @Test + void getClientSettingsJsonFile_encrypted() throws Exception { + + Machine machine = new Machine(); + machine.setPublicKey("PUBKEY"); + + when(machineRepo.findByMachineKeyIndex(anyString())) + .thenReturn(List.of(machine)); + + when(environment.getProperty(anyString(), eq(Boolean.class), eq(false))) + .thenReturn(true); + + Path tempFile = java.nio.file.Files.createTempFile("testEnc", ".json"); + java.nio.file.Files.writeString(tempFile, "data"); + + org.springframework.test.util.ReflectionTestUtils + .setField(service, "clientSettingsDir", + tempFile.getParent().toString()); + + when(keymanagerHelper.getFileSignature(anyString())) + .thenReturn("SIGN"); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("ENCRYPTED_DATA"); + + when(clientCryptoManagerService.csEncrypt(any())) + .thenReturn(cryptoResponse); + + ResponseEntity response = + service.getClientSettingsJsonFile(tempFile.getFileName().toString(), "KEY"); + + assertEquals("ENCRYPTED_DATA", response.getBody()); + } + + @Test + void getClientSettingsJsonFile_fileNotFound() { + + when(machineRepo.findByMachineKeyIndex(anyString())) + .thenReturn(List.of(new Machine())); + + org.springframework.test.util.ReflectionTestUtils + .setField(service, "clientSettingsDir", "/invalid/path"); + + assertThrows(io.mosip.kernel.core.exception.FileNotFoundException.class, + () -> service.getClientSettingsJsonFile("missing.json", "KEY")); + } + + @Test + void getEncryptedData_exception() { + + when(clientCryptoManagerService.csEncrypt(any())) + .thenThrow(new RuntimeException("Crypto error")); + + assertThrows(SyncDataServiceException.class, + () -> org.springframework.test.util.ReflectionTestUtils + .invokeMethod(service, + "getEncryptedData", + "data".getBytes(), + "PUBKEY")); + } + + @Test + void getMachineById_success() throws Exception { + + // Set machineUrl value (VERY IMPORTANT) + org.springframework.test.util.ReflectionTestUtils + .setField(service, "machineUrl", "http://localhost/%s"); + + MachineResponseDto machineResponse = new MachineResponseDto(); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(machineResponse); + wrapper.setErrors(null); + + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenReturn(ResponseEntity.ok("{dummy}")); + + when(objectMapper.readValue( + anyString(), + any(com.fasterxml.jackson.core.type.TypeReference.class))) + .thenReturn(wrapper); + + MachineResponseDto result = + org.springframework.test.util.ReflectionTestUtils + .invokeMethod(service, "getMachineById", "MID"); + + assertNotNull(result); + } + +} diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncRolesServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncRolesServiceImplTest.java new file mode 100644 index 00000000000..75ea6152f76 --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncRolesServiceImplTest.java @@ -0,0 +1,110 @@ +package io.mosip.kernel.syncdata.test.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.kernel.core.authmanager.exception.AuthNException; +import io.mosip.kernel.core.authmanager.exception.AuthZException; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.syncdata.dto.response.RolesResponseDto; +import io.mosip.kernel.syncdata.exception.ParseResponseException; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.syncdata.exception.SyncServiceException; +import io.mosip.kernel.syncdata.service.impl.SyncRolesServiceImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.*; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SyncRolesServiceImplTest { + + @InjectMocks + private SyncRolesServiceImpl service; + + @Mock + private RestTemplate restTemplate; + + @Mock + private ObjectMapper objectMapper; + + private ResponseEntity mockResponse; + + @BeforeEach + void setup() { + mockResponse = new ResponseEntity<>("{\"response\":{}}", HttpStatus.OK); + } + + @Test + void getAllRoles_success() throws Exception { + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockResponse); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(new RolesResponseDto()); + + when(objectMapper.readValue(anyString(), eq(ResponseWrapper.class))).thenReturn(wrapper); + when(objectMapper.writeValueAsString(any())).thenReturn("{}"); + when(objectMapper.readValue(anyString(), eq(RolesResponseDto.class))).thenReturn(new RolesResponseDto()); + + RolesResponseDto result = service.getAllRoles(); + assertNotNull(result); + + verify(restTemplate).exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class)); + verify(objectMapper, atLeastOnce()).readValue(anyString(), eq(ResponseWrapper.class)); + } + + @Test + void getAllRoles_httpUnauthorized_throwsAuthNException() { + HttpClientErrorException ex = HttpClientErrorException.create(HttpStatus.UNAUTHORIZED, + "Unauthorized", HttpHeaders.EMPTY, "{}".getBytes(), null); + + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(ex); + + assertThrows(BadCredentialsException.class, () -> service.getAllRoles()); + } + + @Test + void getAllRoles_httpForbidden_throwsAuthZException() { + HttpClientErrorException ex = HttpClientErrorException.create(HttpStatus.FORBIDDEN, + "Forbidden", HttpHeaders.EMPTY, "{}".getBytes(), null); + + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(ex); + + assertThrows(AccessDeniedException.class, () -> service.getAllRoles()); + } + + @Test + void getAllRoles_httpOtherError_throwsSyncDataServiceException() { + HttpClientErrorException ex = HttpClientErrorException.create(HttpStatus.BAD_REQUEST, + "Bad Request", HttpHeaders.EMPTY, "{}".getBytes(), null); + + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(ex); + + assertThrows(SyncDataServiceException.class, () -> service.getAllRoles()); + } + + @Test + void getAllRoles_responseValidationError_throwsSyncServiceException() throws Exception { + // Simulate response body with errors + ResponseEntity responseWithError = new ResponseEntity<>("{\"errors\":[{\"errorCode\":\"ERR1\",\"message\":\"msg\"}]}", HttpStatus.OK); + + when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenReturn(responseWithError); + + assertThrows(SyncServiceException.class, () -> service.getAllRoles()); + } +} \ No newline at end of file diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncUserDetailsServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncUserDetailsServiceImplTest.java new file mode 100644 index 00000000000..3b74a83044a --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncUserDetailsServiceImplTest.java @@ -0,0 +1,278 @@ +package io.mosip.kernel.syncdata.test.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.kernel.clientcrypto.constant.ClientType; +import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; +import io.mosip.kernel.clientcrypto.service.spi.ClientCryptoManagerService; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.syncdata.dto.RegistrationCenterMachineDto; +import io.mosip.kernel.syncdata.dto.SyncUserDto; +import io.mosip.kernel.syncdata.dto.response.RegistrationCenterUserResponseDto; +import io.mosip.kernel.syncdata.dto.response.UserDetailResponseDto; +import io.mosip.kernel.syncdata.entity.UserDetails; +import com.fasterxml.jackson.core.type.TypeReference; +import io.mosip.kernel.syncdata.exception.DataNotFoundException; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.syncdata.repository.UserDetailsRepository; +import io.mosip.kernel.syncdata.service.impl.SyncUserDetailsServiceImpl; +import io.mosip.kernel.syncdata.utils.MapperUtils; +import org.springframework.security.access.AccessDeniedException; +import io.mosip.kernel.syncdata.utils.SyncMasterDataServiceHelper; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataAccessException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class SyncUserDetailsServiceImplTest { + + @InjectMocks + private SyncUserDetailsServiceImpl service; + + @Mock + private UserDetailsRepository userDetailsRepository; + + @Mock + private SyncMasterDataServiceHelper serviceHelper; + + @Mock + private RestTemplate restTemplate; + + @Mock + private ObjectMapper objectMapper; + + @Mock + private ClientCryptoManagerService clientCryptoManagerService; + + @Mock + private MapperUtils mapper; + + private final String REG_CENTER_ID = "RC01"; + private final String KEY_INDEX = "KEY01"; + + // --------------------------------------------------------- + // 1️⃣ getUsersBasedOnRegistrationCenterId SUCCESS + // --------------------------------------------------------- + @Test + public void testGetUsersBasedOnRegistrationCenterId_Success() { + + UserDetails user = new UserDetails(); + user.setId("user1"); + user.setRegCenterId(REG_CENTER_ID); + user.setIsActive(true); + user.setIsDeleted(false); + user.setLangCode("ENG"); + + when(userDetailsRepository.findByUsersByRegCenterId(REG_CENTER_ID)) + .thenReturn(List.of(user)); + + RegistrationCenterUserResponseDto response = + service.getUsersBasedOnRegistrationCenterId(REG_CENTER_ID); + + assertNotNull(response); + assertEquals(1, response.getRegistrationCenterUsers().size()); + assertEquals("user1", response.getRegistrationCenterUsers().get(0).getUserId()); + } + + // --------------------------------------------------------- + // 2️⃣ DataAccessException + // --------------------------------------------------------- + @Test + public void testGetUsersBasedOnRegistrationCenterId_DataAccessException() { + + when(userDetailsRepository.findByUsersByRegCenterId(REG_CENTER_ID)) + .thenThrow(new DataAccessException("DB error") {}); + + assertThrows(SyncDataServiceException.class, + () -> service.getUsersBasedOnRegistrationCenterId(REG_CENTER_ID)); + } + + // --------------------------------------------------------- + // 3️⃣ No Users Found + // --------------------------------------------------------- + @Test + public void testGetUsersBasedOnRegistrationCenterId_NoUsers() { + + when(userDetailsRepository.findByUsersByRegCenterId(REG_CENTER_ID)) + .thenReturn(List.of()); + + assertThrows(DataNotFoundException.class, + () -> service.getUsersBasedOnRegistrationCenterId(REG_CENTER_ID)); + } + + // --------------------------------------------------------- + // 4️⃣ getUserDetailsFromAuthServer SUCCESS + // --------------------------------------------------------- + @Test + public void testGetUserDetailsFromAuthServer_Success() throws Exception { + + String responseBody = "{\"response\":{}}"; + + ResponseEntity responseEntity = + new ResponseEntity<>(responseBody, HttpStatus.OK); + + when(restTemplate.postForEntity(anyString(), any(), eq(String.class))) + .thenReturn(responseEntity); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(new UserDetailResponseDto()); + + when(objectMapper.readValue(eq(responseBody), any(TypeReference.class))) + .thenReturn(wrapper); + + UserDetailResponseDto result = + service.getUserDetailsFromAuthServer(List.of("user1")); + + assertNotNull(result); + } + + // --------------------------------------------------------- + // 5️⃣ 401 Unauthorized + // --------------------------------------------------------- + @Test + public void testGetUserDetailsFromAuthServer_401() { + + HttpClientErrorException ex = + HttpClientErrorException.create(HttpStatus.UNAUTHORIZED, + "Unauthorized", HttpHeaders.EMPTY, null, null); + + when(restTemplate.postForEntity(anyString(), any(), eq(String.class))) + .thenThrow(ex); + + assertThrows(BadCredentialsException.class, + () -> service.getUserDetailsFromAuthServer(List.of("user1"))); + } + + // --------------------------------------------------------- + // 6️⃣ 403 Forbidden + // --------------------------------------------------------- + @Test + public void testGetUserDetailsFromAuthServer_403() { + + HttpClientErrorException ex = + HttpClientErrorException.create(HttpStatus.FORBIDDEN, + "Forbidden", HttpHeaders.EMPTY, null, null); + + when(restTemplate.postForEntity(anyString(), any(), eq(String.class))) + .thenThrow(ex); + + assertThrows(AccessDeniedException.class, + () -> service.getUserDetailsFromAuthServer(List.of("user1"))); + } + + // --------------------------------------------------------- + // 7️⃣ Other HTTP Error + // --------------------------------------------------------- + @Test + public void testGetUserDetailsFromAuthServer_OtherError() { + + HttpServerErrorException ex = + HttpServerErrorException.create(HttpStatus.INTERNAL_SERVER_ERROR, + "Error", HttpHeaders.EMPTY, null, null); + + when(restTemplate.postForEntity(anyString(), any(), eq(String.class))) + .thenThrow(ex); + + assertThrows(SyncDataServiceException.class, + () -> service.getUserDetailsFromAuthServer(List.of("user1"))); + } + + // --------------------------------------------------------- + // 8️⃣ getAllUserDetailsBasedOnKeyIndex SUCCESS + // --------------------------------------------------------- + @Test + public void testGetAllUserDetailsBasedOnKeyIndex_Success() throws Exception { + + RegistrationCenterMachineDto machineDto = new RegistrationCenterMachineDto(); + machineDto.setRegCenterId(REG_CENTER_ID); + machineDto.setPublicKey("PUBKEY"); + + when(serviceHelper.getRegistrationCenterMachine(null, KEY_INDEX)) + .thenReturn(machineDto); + + // mock users + UserDetails user = new UserDetails(); + user.setId("user1"); + user.setRegCenterId(REG_CENTER_ID); + user.setIsActive(true); + user.setIsDeleted(false); + user.setLangCode("ENG"); + + when(userDetailsRepository.findByUsersByRegCenterId(REG_CENTER_ID)) + .thenReturn(List.of(user)); + + // mock auth response + UserDetailResponseDto userDetailResponseDto = new UserDetailResponseDto(); + userDetailResponseDto.setMosipUserDtoList(new ArrayList<>()); + + SyncUserDetailsServiceImpl spy = Mockito.spy(service); + doReturn(userDetailResponseDto) + .when(spy).getUserDetailsFromAuthServer(any()); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("encryptedData"); + + SyncUserDto result = + spy.getAllUserDetailsBasedOnKeyIndex(KEY_INDEX); + + assertNotNull(result); + } + + // --------------------------------------------------------- + // 9️⃣ getAllUserDetailsBasedOnKeyIndexV2 SUCCESS + // --------------------------------------------------------- + @Test + public void testGetAllUserDetailsBasedOnKeyIndexV2_Success() throws Exception { + + RegistrationCenterMachineDto machineDto = new RegistrationCenterMachineDto(); + machineDto.setRegCenterId(REG_CENTER_ID); + machineDto.setPublicKey("PUBKEY"); + machineDto.setClientType(ClientType.TPM); + + when(serviceHelper.getRegistrationCenterMachine(null, KEY_INDEX)) + .thenReturn(machineDto); + + UserDetails user = new UserDetails(); + user.setId("user1"); + user.setRegCenterId(REG_CENTER_ID); + user.setIsActive(true); + user.setIsDeleted(false); + user.setLangCode("ENG"); + + when(userDetailsRepository.findByUsersByRegCenterId(REG_CENTER_ID)) + .thenReturn(List.of(user)); + + when(mapper.getObjectAsJsonString(any())).thenReturn("json"); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("encryptedData"); + + when(clientCryptoManagerService.csEncrypt(any())) + .thenReturn(cryptoResponse); + + SyncUserDto result = + service.getAllUserDetailsBasedOnKeyIndexV2(KEY_INDEX); + + assertNotNull(result); + assertEquals("encryptedData", result.getUserDetails()); + } + +} \ No newline at end of file From 8139b9b9d6a4ffdbc8631194e8b41a11e0a5ece6 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 14:09:40 +0530 Subject: [PATCH 02/19] [MOSIP-42804] - Sonar coverage added Signed-off-by: Nidhi0201 --- .../impl/CacheManagementServiceImplTest.java | 89 +++++++++++++++++++ .../impl/SyncAuthTokenServiceImplTest.java | 5 +- 2 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java diff --git a/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java new file mode 100644 index 00000000000..0436834d52b --- /dev/null +++ b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java @@ -0,0 +1,89 @@ +package io.mosip.kernel.masterdata.test.service.impl; + +import io.mosip.kernel.masterdata.service.impl.CacheManagementServiceImpl; +import io.mosip.kernel.masterdata.utils.CacheName; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.Mockito.*; + +class CacheManagementServiceImplTest { + + @InjectMocks + private CacheManagementServiceImpl cacheService; + + @Mock + private CacheManager cacheManager; + + @Mock + private Cache mockCache1; + + @Mock + private Cache mockCache2; + + @BeforeEach + void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + void clearCacheByCacheName_existingCache_clearsOnlyMatched() { + when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("CACHE1", "CACHE2")); + when(cacheManager.getCache("CACHE1")).thenReturn(mockCache1); + when(cacheManager.getCache("CACHE2")).thenReturn(mockCache2); + + cacheService.clearCacheByCacheName(CacheName.BLOCK_LISTED_WORDS); + + verify(mockCache2, never()).clear(); + } + + @Test + void clearCacheByCacheName_cacheNotFound_doesNotThrow() { + when(cacheManager.getCacheNames()).thenReturn(Collections.singletonList("CACHE2")); + when(cacheManager.getCache("CACHE2")).thenReturn(mockCache2); + + assertDoesNotThrow(() -> cacheService.clearCacheByCacheName(CacheName.BLOCK_LISTED_WORDS)); + + verify(mockCache2, never()).clear(); + } + + @Test + void clearCacheByCacheName_nullCache_ignored() { + when(cacheManager.getCacheNames()).thenReturn(Collections.singletonList("CACHE1")); + when(cacheManager.getCache("CACHE1")).thenReturn(null); + + assertDoesNotThrow(() -> cacheService.clearCacheByCacheName(CacheName.BLOCK_LISTED_WORDS)); + } + + @Test + void clearCache_clearsAllCaches() { + when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("CACHE1", "CACHE2")); + when(cacheManager.getCache("CACHE1")).thenReturn(mockCache1); + when(cacheManager.getCache("CACHE2")).thenReturn(mockCache2); + + cacheService.clearCache(); + + verify(mockCache1).clear(); + verify(mockCache2).clear(); + } + + @Test + void clearCache_nullCaches_ignored() { + when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("CACHE1", "CACHE2")); + when(cacheManager.getCache("CACHE1")).thenReturn(null); + when(cacheManager.getCache("CACHE2")).thenReturn(mockCache2); + + cacheService.clearCache(); + + verify(mockCache2).clear(); + } +} \ No newline at end of file diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java index db8e8e6fcfa..e80c29df247 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java @@ -1,11 +1,8 @@ package io.mosip.kernel.syncdata.test.service.impl; -import com.auth0.jwt.impl.JWTParser; -import com.auth0.jwt.interfaces.Header; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import io.mosip.kernel.clientcrypto.exception.ClientCryptoException; import io.mosip.kernel.clientcrypto.service.impl.ClientCryptoFacade; import io.mosip.kernel.core.authmanager.model.AuthNResponse; import io.mosip.kernel.core.http.ResponseWrapper; @@ -108,7 +105,7 @@ void getAuthToken_invalidRequest_throwsRequestException() { // ======================= SUCCESS ======================= @Test - void getAuthToken_success_verifiedTrue() throws Exception { + void getAuthToken_emptyTokenResponse_throwsRequestException() throws Exception { LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); // Create JWT-like token From 56ad49f8655ef1452c552d0ce2625b65ab1282dd Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 16:15:35 +0530 Subject: [PATCH 03/19] [MOSIP-42804] - added more coverage Signed-off-by: Nidhi0201 --- .../SyncMasterDataServiceHelperTest.java | 1509 +++++++++++++++++ 1 file changed, 1509 insertions(+) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java index bc91ab8cd68..4ab1827ee76 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java @@ -4,7 +4,10 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.mosip.kernel.core.exception.ServiceError; +import com.fasterxml.jackson.core.type.TypeReference; +import io.mosip.kernel.syncdata.entity.id.ApplicantValidDocumentID; import io.mosip.kernel.syncdata.entity.id.HolidayID; +import io.mosip.kernel.syncdata.exception.AdminServiceException; import io.mosip.kernel.syncdata.exception.SyncDataServiceException; import io.mosip.kernel.syncdata.exception.SyncServiceException; import org.mockito.InjectMocks; @@ -46,6 +49,7 @@ import org.springframework.web.client.RestTemplate; import io.mosip.kernel.core.exception.ExceptionUtils; +import java.net.URI; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -166,6 +170,9 @@ public class SyncMasterDataServiceHelperTest { @Mock private ObjectMapper objectMapper; + @Mock + private ApplicantValidDocumentRespository applicantValidDocumentRepository; + @Autowired private MockMvc mockMvc; @@ -3226,4 +3233,1506 @@ public void testDataAccessException_ShouldThrowSyncDataServiceException() { LocalDateTime.now()); } + @Test + public void testGetValidDocuments_NoChangesFound() throws Exception { + + // Arrange + when(validDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + // Act + CompletableFuture> future = + syncMasterData.getValidDocuments( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + // Assert + assertNull(result); // method returns completedFuture(null) + } + + @Test + public void testGetValidDocuments_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + // Make isChangesFound return true + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(validDocumentRepository.findAllLatestCreatedUpdateDeleted( + any(), any())) + .thenReturn(Collections.emptyList()); + + // Act + CompletableFuture> future = + syncMasterData.getValidDocuments(null, now); + + List result = future.get(); + + // Assert + assertNull(result); // because convert method returns null for empty list + } + + @Test + public void testGetValidDocuments_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + // Changes found + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(validDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + // Prepare entity + ValidDocument entity = new ValidDocument(); + entity.setDocTypeCode("DOC1"); + entity.setDocCategoryCode("CAT1"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(validDocumentRepository.findAllLatestCreatedUpdateDeleted( + any(), any())) + .thenReturn(Collections.singletonList(entity)); + + // Act + CompletableFuture> future = + syncMasterData.getValidDocuments(lastUpdated, now); + + List result = future.get(); + + // Assert + assertNotNull(result); + assertEquals(1, result.size()); + + ValidDocumentDto dto = result.get(0); + + assertEquals("DOC1", dto.getDocTypeCode()); + assertEquals("CAT1", dto.getDocCategoryCode()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetValidDocuments_EmptyRepositoryResult() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(3); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(validDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(validDocumentRepository.findAllLatestCreatedUpdateDeleted( + any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getValidDocuments(lastUpdated, now); + + List result = future.get(); + + assertNull(result); // convert method returns null for empty list + } + + @Test(expected = SyncDataServiceException.class) + public void testGetValidDocuments_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(validDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(validDocumentRepository.findAllLatestCreatedUpdateDeleted( + any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getValidDocuments(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetRegistrationCenterMachines_NoChangesFound() throws Exception { + + // Arrange + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + // Act + CompletableFuture> future = + syncMasterData.getRegistrationCenterMachines( + "1001", + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC), + null); + + List result = future.get(); + + // Assert + assertNull(result); + } + + @Test + public void testGetRegistrationCenterMachines_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterMachines( + "1001", + null, + now, + null); + + List result = future.get(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetRegistrationCenterMachines_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + Machine machine = new Machine(); + machine.setId("M1"); + machine.setRegCenterId("1001"); + machine.setIsActive(true); + machine.setIsDeleted(false); + machine.setLangCode("eng"); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenReturn(Collections.singletonList(machine)); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterMachines( + "1001", + lastUpdated, + now, + null); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + RegistrationCenterMachineDto dto = result.get(0); + + assertEquals("M1", dto.getMachineId()); + assertEquals("1001", dto.getRegCenterId()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetRegistrationCenterMachines_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterMachines( + "1001", + lastUpdated, + now, + null); + + List result = future.get(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetRegistrationCenterMachines_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(machineRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(machineRepository.findMachineLatestCreatedUpdatedDeleted( + any(), any(), any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getRegistrationCenterMachines("1001", lastUpdated, now, null) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetRegistrationCenterUsers_NoChangesFound() throws Exception { + + // Arrange + when(userDetailsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + // Act + CompletableFuture> future = + syncMasterData.getRegistrationCenterUsers( + "1001", + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + // Assert + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetRegistrationCenterUsers_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(userDetailsRepository.findAllLatestCreatedUpdatedDeleted( + any(), any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterUsers( + "1001", + null, + now); + + List result = future.get(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetRegistrationCenterUsers_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(userDetailsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + UserDetails user = new UserDetails(); + user.setId("U1"); + user.setRegCenterId("1001"); + user.setIsActive(true); + user.setIsDeleted(false); + user.setLangCode("eng"); + + when(userDetailsRepository.findAllLatestCreatedUpdatedDeleted( + any(), any(), any())) + .thenReturn(Collections.singletonList(user)); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterUsers( + "1001", + lastUpdated, + now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + RegistrationCenterUserDto dto = result.get(0); + + assertEquals("U1", dto.getUserId()); + assertEquals("1001", dto.getRegCenterId()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetRegistrationCenterUsers_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(userDetailsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(userDetailsRepository.findAllLatestCreatedUpdatedDeleted( + any(), any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getRegistrationCenterUsers( + "1001", + lastUpdated, + now); + + List result = future.get(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetRegistrationCenterUsers_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(userDetailsRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(userDetailsRepository.findAllLatestCreatedUpdatedDeleted( + any(), any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getRegistrationCenterUsers("1001", lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetApplicantValidDocument_NoChangesFound() throws Exception { + + when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getApplicantValidDocument( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetApplicantValidDocument_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getApplicantValidDocument(null, now); + + List result = future.get(); + + assertNull(result); // convert method returns null + } + + @Test + public void testGetApplicantValidDocument_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + // Prepare composite ID + ApplicantValidDocumentID id = new ApplicantValidDocumentID(); + id.setAppTypeCode("APP1"); + id.setDocTypeCode("DOC1"); + id.setDocCatCode("CAT1"); + + ApplicantValidDocument entity = new ApplicantValidDocument(); + entity.setApplicantValidDocumentId(id); + entity.setLangCode("eng"); + entity.setIsActive(true); + entity.setIsDeleted(false); + + when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getApplicantValidDocument(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + ApplicantValidDocumentDto dto = result.get(0); + + assertEquals("APP1", dto.getAppTypeCode()); + assertEquals("DOC1", dto.getDocTypeCode()); + assertEquals("CAT1", dto.getDocCatCode()); + assertEquals("eng", dto.getLangCode()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + } + + @Test + public void testGetApplicantValidDocument_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getApplicantValidDocument(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetApplicantValidDocument_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getApplicantValidDocument(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetAppAuthenticationMethodDetails_NoChangesFound() throws Exception { + + when(appAuthenticationMethodRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getAppAuthenticationMethodDetails( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetAppAuthenticationMethodDetails_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(appAuthenticationMethodRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getAppAuthenticationMethodDetails(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetAppAuthenticationMethodDetails_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appAuthenticationMethodRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + AppAuthenticationMethod entity = new AppAuthenticationMethod(); + entity.setAppId("APP1"); + entity.setProcessId("PROC1"); + entity.setRoleCode("ROLE1"); + entity.setAuthMethodCode("AUTH1"); + entity.setMethodSequence(1); + entity.setLangCode("eng"); + entity.setIsActive(true); + entity.setIsDeleted(false); + + when(appAuthenticationMethodRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getAppAuthenticationMethodDetails(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + AppAuthenticationMethodDto dto = result.get(0); + + assertEquals("APP1", dto.getAppId()); + assertEquals("PROC1", dto.getProcessId()); + assertEquals("ROLE1", dto.getRoleCode()); + assertEquals("AUTH1", dto.getAuthMethodCode()); + assertEquals(Integer.valueOf(1), dto.getMethodSequence()); + assertEquals("eng", dto.getLangCode()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + } + + @Test + public void testGetAppAuthenticationMethodDetails_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appAuthenticationMethodRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(appAuthenticationMethodRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getAppAuthenticationMethodDetails(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetAppAuthenticationMethodDetails_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appAuthenticationMethodRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(appAuthenticationMethodRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getAppAuthenticationMethodDetails(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetAppRolePriorityDetails_NoChangesFound() throws Exception { + + when(appRolePriorityRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getAppRolePriorityDetails( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetAppRolePriorityDetails_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(appRolePriorityRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getAppRolePriorityDetails(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetAppRolePriorityDetails_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appRolePriorityRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + AppRolePriority entity = new AppRolePriority(); + entity.setAppId("APP1"); + entity.setProcessId("PROC1"); + entity.setRoleCode("ROLE1"); + entity.setPriority(5); + entity.setLangCode("eng"); + entity.setIsActive(true); + entity.setIsDeleted(false); + + when(appRolePriorityRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getAppRolePriorityDetails(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + AppRolePriorityDto dto = result.get(0); + + assertEquals("APP1", dto.getAppId()); + assertEquals("PROC1", dto.getProcessId()); + assertEquals("ROLE1", dto.getRoleCode()); + assertEquals(Integer.valueOf(5), dto.getPriority()); + assertEquals("eng", dto.getLangCode()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + } + + @Test + public void testGetAppRolePriorityDetails_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appRolePriorityRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(appRolePriorityRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getAppRolePriorityDetails(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetAppRolePriorityDetails_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(appRolePriorityRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(appRolePriorityRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getAppRolePriorityDetails(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetScreenAuthorizationDetails_NoChangesFound() throws Exception { + + when(screenAuthorizationRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getScreenAuthorizationDetails( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetScreenAuthorizationDetails_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(screenAuthorizationRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getScreenAuthorizationDetails(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetScreenAuthorizationDetails_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(screenAuthorizationRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + ScreenAuthorization entity = new ScreenAuthorization(); + entity.setScreenId("SCR001"); + entity.setRoleCode("ADMIN"); + entity.setIsPermitted(true); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(screenAuthorizationRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getScreenAuthorizationDetails(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + ScreenAuthorizationDto dto = result.get(0); + + assertEquals("SCR001", dto.getScreenId()); + assertEquals("ADMIN", dto.getRoleCode()); + assertTrue(dto.getIsPermitted()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetScreenAuthorizationDetails_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(screenAuthorizationRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(screenAuthorizationRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getScreenAuthorizationDetails(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetScreenAuthorizationDetails_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + when(screenAuthorizationRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(screenAuthorizationRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getScreenAuthorizationDetails(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetProcessList_NoChangesFound() throws Exception { + + when(processListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getProcessList( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetProcessList_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(processListRepository + .findByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getProcessList(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetProcessList_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(processListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + ProcessList entity = new ProcessList(); + entity.setId("P001"); + entity.setName("Registration"); + entity.setDescr("Registration Process"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(processListRepository + .findByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getProcessList(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + ProcessListDto dto = result.get(0); + + assertEquals("P001", dto.getId()); + assertEquals("Registration", dto.getName()); + assertEquals("Registration Process", dto.getDescr()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetProcessList_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(processListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(processListRepository + .findByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getProcessList(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetProcessList_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(processListRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(processListRepository + .findByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getProcessList(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetSyncJobDefDetails_NoChangesFound() throws Exception { + + when(syncJobDefRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getSyncJobDefDetails( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetSyncJobDefDetails_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(syncJobDefRepository + .findLatestByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getSyncJobDefDetails(null, now); + + List result = future.get(); + + assertNull(result); // convert method returns null + } + + @Test + public void testGetSyncJobDefDetails_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(syncJobDefRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + SyncJobDef entity = new SyncJobDef(); + entity.setId("JOB001"); + entity.setName("Sync Master Data"); + entity.setApiName("syncMasterDataApi"); + entity.setParentSyncJobId("PARENT001"); + entity.setSyncFreq("DAILY"); + entity.setLockDuration("30"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(syncJobDefRepository + .findLatestByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getSyncJobDefDetails(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + SyncJobDefDto dto = result.get(0); + + assertEquals("JOB001", dto.getId()); + assertEquals("Sync Master Data", dto.getName()); + assertEquals("syncMasterDataApi", dto.getApiName()); + assertEquals("PARENT001", dto.getParentSyncJobId()); + assertEquals("DAILY", dto.getSyncFreq()); + assertEquals("30", dto.getLockDuration()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetSyncJobDefDetails_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(syncJobDefRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(syncJobDefRepository + .findLatestByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getSyncJobDefDetails(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = AdminServiceException.class) + public void testGetSyncJobDefDetails_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(syncJobDefRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(syncJobDefRepository + .findLatestByLastUpdatedTimeAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getSyncJobDefDetails(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetScreenDetails_NoChangesFound() throws Exception { + + when(screenDetailRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getScreenDetails( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetScreenDetails_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(screenDetailRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getScreenDetails(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetScreenDetails_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(screenDetailRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + ScreenDetail entity = new ScreenDetail(); + entity.setId("SCR001"); + entity.setAppId("APP01"); + entity.setName("Home Screen"); + entity.setDescr("Main Screen"); + entity.setIsActive(true); + entity.setIsDeleted(false); + entity.setLangCode("eng"); + + when(screenDetailRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getScreenDetails(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + ScreenDetailDto dto = result.get(0); + + assertEquals("SCR001", dto.getId()); + assertEquals("APP01", dto.getAppId()); + assertEquals("Home Screen", dto.getName()); + assertEquals("Main Screen", dto.getDescr()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + assertEquals("eng", dto.getLangCode()); + } + + @Test + public void testGetScreenDetails_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(screenDetailRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(screenDetailRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getScreenDetails(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetScreenDetails_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(screenDetailRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(screenDetailRepository + .findByLastUpdatedAndCurrentTimeStamp(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getScreenDetails(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetPermittedConfig_NoChangesFound() throws Exception { + + when(permittedLocalConfigRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getPermittedConfig( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetPermittedConfig_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(permittedLocalConfigRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(Collections.emptyList()); + + CompletableFuture> future = + syncMasterData.getPermittedConfig(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetPermittedConfig_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(permittedLocalConfigRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + PermittedLocalConfig entity = new PermittedLocalConfig(); + entity.setCode("CFG001"); + entity.setName("BiometricEnabled"); + entity.setType("BOOLEAN"); + entity.setIsActive(true); + entity.setIsDeleted(false); + + when(permittedLocalConfigRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getPermittedConfig(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + PermittedConfigDto dto = result.get(0); + + assertEquals("CFG001", dto.getCode()); + assertEquals("BiometricEnabled", dto.getName()); + assertEquals("BOOLEAN", dto.getType()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + } + + @Test + public void testGetPermittedConfig_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(permittedLocalConfigRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(permittedLocalConfigRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getPermittedConfig(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetPermittedConfig_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(permittedLocalConfigRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(permittedLocalConfigRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getPermittedConfig(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + + @Test + public void testGetLanguageList_NoChangesFound() throws Exception { + + when(languageRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(null); // makes isChangesFound return false + + CompletableFuture> future = + syncMasterData.getLanguageList( + LocalDateTime.now(ZoneOffset.UTC).minusDays(1), + LocalDateTime.now(ZoneOffset.UTC)); + + List result = future.get(); + + assertNull(result); + } + + @Test + public void testGetLanguageList_LastUpdatedNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + CompletableFuture> future = + syncMasterData.getLanguageList(null, now); + + List result = future.get(); + + assertNull(result); // convert returns null + } + + @Test + public void testGetLanguageList_WithData_ShouldMapFields() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(languageRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + Language entity = new Language(); + entity.setCode("eng"); + entity.setName("English"); + entity.setFamily("Indo-European"); + entity.setNativeName("English"); + entity.setIsActive(true); + entity.setIsDeleted(false); + + when(languageRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(Collections.singletonList(entity)); + + CompletableFuture> future = + syncMasterData.getLanguageList(lastUpdated, now); + + List result = future.get(); + + assertNotNull(result); + assertEquals(1, result.size()); + + LanguageDto dto = result.get(0); + + assertEquals("eng", dto.getCode()); + assertEquals("English", dto.getName()); + assertEquals("Indo-European", dto.getFamily()); + assertEquals("English", dto.getNativeName()); + assertTrue(dto.getIsActive()); + assertFalse(dto.getIsDeleted()); + } + + @Test + public void testGetLanguageList_RepositoryReturnsNull() throws Exception { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(1); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(languageRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(languageRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenReturn(null); + + CompletableFuture> future = + syncMasterData.getLanguageList(lastUpdated, now); + + List result = future.get(); + + assertNull(result); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetLanguageList_DataAccessException() throws Throwable { + + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + LocalDateTime lastUpdated = now.minusDays(2); + + EntityDtimes entityDtimes = new EntityDtimes(now, null, null); + + when(languageRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + .thenReturn(entityDtimes); + + when(languageRepository + .findAllLatestCreatedUpdateDeleted(any(), any())) + .thenThrow(new DataAccessResourceFailureException("DB error")); + + try { + syncMasterData + .getLanguageList(lastUpdated, now) + .get(); + } catch (ExecutionException e) { + throw e.getCause(); + } + } + } From 28e95d1ae336d3deb1118209a4f6795fdbf8e700 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 16:26:53 +0530 Subject: [PATCH 04/19] [MOSIP-42804] - code rabbit comments fixed Signed-off-by: Nidhi0201 --- .../impl/CacheManagementServiceImplTest.java | 6 ++--- .../SyncMasterDataServiceHelperTest.java | 18 --------------- .../impl/SyncAuthTokenServiceImplTest.java | 23 ------------------- .../impl/SyncMasterDataServiceImplTest.java | 2 -- 4 files changed, 3 insertions(+), 46 deletions(-) diff --git a/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java index 0436834d52b..693d45eade0 100644 --- a/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java +++ b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java @@ -37,9 +37,9 @@ void setup() { @Test void clearCacheByCacheName_existingCache_clearsOnlyMatched() { - when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("CACHE1", "CACHE2")); - when(cacheManager.getCache("CACHE1")).thenReturn(mockCache1); - when(cacheManager.getCache("CACHE2")).thenReturn(mockCache2); + when(cacheManager.getCacheNames()).thenReturn(Arrays.asList("blocklisted-words", "other-cache")); + when(cacheManager.getCache("blocklisted-words")).thenReturn(mockCache1); + when(cacheManager.getCache("other-cache")).thenReturn(mockCache2); cacheService.clearCacheByCacheName(CacheName.BLOCK_LISTED_WORDS); diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java index 4ab1827ee76..b0824064246 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java @@ -1,10 +1,6 @@ package io.mosip.kernel.syncdata.test.service; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import io.mosip.kernel.core.exception.ServiceError; -import com.fasterxml.jackson.core.type.TypeReference; import io.mosip.kernel.syncdata.entity.id.ApplicantValidDocumentID; import io.mosip.kernel.syncdata.entity.id.HolidayID; import io.mosip.kernel.syncdata.exception.AdminServiceException; @@ -13,7 +9,6 @@ import org.mockito.InjectMocks; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import io.mosip.kernel.clientcrypto.constant.ClientType; import io.mosip.kernel.core.exception.FileNotFoundException; import io.mosip.kernel.core.http.ResponseWrapper; @@ -47,9 +42,7 @@ import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.client.RestTemplate; -import io.mosip.kernel.core.exception.ExceptionUtils; -import java.net.URI; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -2291,15 +2284,6 @@ public void testGetLocationHierarchyList_Success() throws Exception { assertEquals("Country", result.get(0).getHierarchyLevelName()); } -// @Test(expected = RuntimeException.class) -// public void testGetLocationHierarchyList_WhenRestTemplateFails() { -// -// when(restTemplate.getForEntity(any(), eq(String.class))) -// .thenThrow(new RuntimeException("Failure")); -// -// syncMasterData.getLocationHierarchyList(null); -// } - @Test(expected = SyncServiceException.class) public void testGetLocationHierarchyList_WithValidationErrors() { @@ -3653,8 +3637,6 @@ public void testGetApplicantValidDocument_LastUpdatedNull() throws Exception { LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); - EntityDtimes entityDtimes = new EntityDtimes(now, null, null); - when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) .thenReturn(Collections.emptyList()); diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java index e80c29df247..200ebb46ef5 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java @@ -76,19 +76,6 @@ void setup() { ReflectionTestUtils.setField(service, "refreshAuthTokenInternalUrl", "http://refresh"); } - // ===================================================== - // getAuthToken SUCCESS - // ===================================================== - // ======== HELPER TO CREATE JWT-LIKE TOKEN ======== - private String createToken(String kid, String machineName, LocalDateTime timestamp) throws Exception { - String headerJson = "{\"kid\":\"" + kid + "\"}"; - String payloadJson = "{\"machineName\":\"" + machineName + "\",\"timestamp\":\"" + timestamp + "\",\"authType\":\"NEW\"}"; - String signature = "sig"; - - return Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + - Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + - Base64.getUrlEncoder().encodeToString(signature.getBytes()); - } @Test void getAuthToken_invalidRequest_throwsRequestException() { @@ -151,16 +138,6 @@ void getAuthToken_emptyTokenResponse_throwsRequestException() throws Exception { } - // ===================================================== - // INVALID TOKEN FORMAT - // ===================================================== - - @Test - void getAuthToken_invalidFormat() { - assertThrows(RequestException.class, - () -> service.getAuthToken("invalid.token")); - } - // ===================================================== // TIMESTAMP VALIDATION // ===================================================== diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java index 5dcfe39253c..46f8dbc3afa 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncMasterDataServiceImplTest.java @@ -1,12 +1,10 @@ package io.mosip.kernel.syncdata.test.service.impl; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; import io.mosip.kernel.clientcrypto.service.spi.ClientCryptoManagerService; import io.mosip.kernel.core.http.ResponseWrapper; import io.mosip.kernel.keymanagerservice.entity.CACertificateStore; -import io.mosip.kernel.syncdata.constant.MasterDataErrorCode; import io.mosip.kernel.syncdata.dto.*; import io.mosip.kernel.syncdata.dto.response.*; import io.mosip.kernel.syncdata.entity.Machine; From ac822a50486aa063fbac75fb9f5399070c6dca69 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 16:31:47 +0530 Subject: [PATCH 05/19] [MOSIP-42804] - code rabbit comments fixed Signed-off-by: Nidhi0201 --- .../SyncMasterDataServiceHelperTest.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java index b0824064246..da9d0ac718d 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java @@ -163,9 +163,6 @@ public class SyncMasterDataServiceHelperTest { @Mock private ObjectMapper objectMapper; - @Mock - private ApplicantValidDocumentRespository applicantValidDocumentRepository; - @Autowired private MockMvc mockMvc; @@ -3619,7 +3616,7 @@ public void testGetRegistrationCenterUsers_DataAccessException() throws Throwabl @Test public void testGetApplicantValidDocument_NoChangesFound() throws Exception { - when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + when(applicantValidDocumentRespository.getMaxCreatedDateTimeMaxUpdatedDateTime()) .thenReturn(null); // makes isChangesFound return false CompletableFuture> future = @@ -3637,7 +3634,7 @@ public void testGetApplicantValidDocument_LastUpdatedNull() throws Exception { LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); - when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + when(applicantValidDocumentRespository.findAllByTimeStamp(any(), any())) .thenReturn(Collections.emptyList()); CompletableFuture> future = @@ -3655,7 +3652,7 @@ public void testGetApplicantValidDocument_WithData_ShouldMapFields() throws Exce LocalDateTime lastUpdated = now.minusDays(2); EntityDtimes entityDtimes = new EntityDtimes(now, null, null); - when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + when(applicantValidDocumentRespository.getMaxCreatedDateTimeMaxUpdatedDateTime()) .thenReturn(entityDtimes); // Prepare composite ID @@ -3670,7 +3667,7 @@ public void testGetApplicantValidDocument_WithData_ShouldMapFields() throws Exce entity.setIsActive(true); entity.setIsDeleted(false); - when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + when(applicantValidDocumentRespository.findAllByTimeStamp(any(), any())) .thenReturn(Collections.singletonList(entity)); CompletableFuture> future = @@ -3698,10 +3695,10 @@ public void testGetApplicantValidDocument_RepositoryReturnsNull() throws Excepti LocalDateTime lastUpdated = now.minusDays(1); EntityDtimes entityDtimes = new EntityDtimes(now, null, null); - when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + when(applicantValidDocumentRespository.getMaxCreatedDateTimeMaxUpdatedDateTime()) .thenReturn(entityDtimes); - when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + when(applicantValidDocumentRespository.findAllByTimeStamp(any(), any())) .thenReturn(null); CompletableFuture> future = @@ -3719,10 +3716,10 @@ public void testGetApplicantValidDocument_DataAccessException() throws Throwable LocalDateTime lastUpdated = now.minusDays(2); EntityDtimes entityDtimes = new EntityDtimes(now, null, null); - when(applicantValidDocumentRepository.getMaxCreatedDateTimeMaxUpdatedDateTime()) + when(applicantValidDocumentRespository.getMaxCreatedDateTimeMaxUpdatedDateTime()) .thenReturn(entityDtimes); - when(applicantValidDocumentRepository.findAllByTimeStamp(any(), any())) + when(applicantValidDocumentRespository.findAllByTimeStamp(any(), any())) .thenThrow(new DataAccessResourceFailureException("DB error")); try { From 5bb511cf43a55a798817a27d62adee7d413ac819 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 19:32:10 +0530 Subject: [PATCH 06/19] [MOSIP-42804] - added test case Signed-off-by: Nidhi0201 --- .../WebsubCallbackControllerTest.java | 173 +++++++++++++++++- .../PartnerCACertEventSubscriberTest.java | 126 +++++++++++++ 2 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java index 4a8cdc4f9de..8f8cc022b71 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java @@ -8,8 +8,10 @@ import io.mosip.kernel.core.websub.model.Event; import io.mosip.kernel.core.websub.model.EventModel; import io.mosip.kernel.core.websub.model.Type; +import io.mosip.kernel.partnercertservice.dto.CACertificateRequestDto; import io.mosip.kernel.partnercertservice.dto.CACertificateResponseDto; import io.mosip.kernel.partnercertservice.service.spi.PartnerCertificateManagerService; +import io.mosip.kernel.syncdata.controller.WebsubCallbackController; import io.mosip.kernel.syncdata.test.TestBootApplication; import io.mosip.kernel.websub.api.verifier.AuthenticatedContentVerifier; import org.bouncycastle.crypto.digests.SHA1Digest; @@ -18,6 +20,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; @@ -32,13 +36,18 @@ import org.springframework.web.client.RestTemplate; import jakarta.xml.bind.DatatypeConverter; + +import java.lang.reflect.Field; import java.time.LocalDateTime; import java.time.ZoneOffset; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import static org.mockito.Mockito.lenient; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; @@ -49,7 +58,10 @@ public class WebsubCallbackControllerTest { private static final String CERTIFICATE_DATA_SHARE_URL = "certChainDatashareUrl"; private static final String PARTNER_DOMAIN = "partnerDomain"; - + + @InjectMocks + private WebsubCallbackController controller; + @Mock private ObjectMapper objectMapper; @@ -77,10 +89,11 @@ public class WebsubCallbackControllerTest { private MockRestServiceServer mockRestServiceServer; @Before - public void setUp() { + public void setUp() throws Exception { mockRestServiceServer = MockRestServiceServer.bindTo(restTemplate) .ignoreExpectOrder(true) .build(); + setField("partnerAllowedDomains", Arrays.asList("FTM", "DEVICE")); } @@ -179,4 +192,158 @@ private String getHubSignature(byte[] body) { return "SHA1="+DatatypeConverter.printHexBinary(result).toLowerCase(); } + private void setField(String name, Object value) throws Exception { + Field field = WebsubCallbackController.class.getDeclaredField(name); + field.setAccessible(true); + field.set(controller, value); + } + + private EventModel buildEvent(Map dataMap) { + + EventModel eventModel = new EventModel(); // DO NOT mock this + Event event = mock(Event.class); // mock real Event class + + when(event.getData()).thenReturn(dataMap); + + eventModel.setEvent(event); + + return eventModel; + } + + /** + * ✅ Success Flow + */ + @Test + public void handleCACertificate_success() throws Exception { + + Map data = new HashMap<>(); + data.put("partnerDomain", "FTM"); + data.put("certChainDatashareUrl", "http://test-url"); + + EventModel eventModel = buildEvent(data); + + String certificateResponse = "{\"response\":{}}"; + + when(restTemplate.getForObject("http://test-url", String.class)) + .thenReturn(certificateResponse); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setErrors(null); + + controller.handleCACertificate(eventModel); + + ArgumentCaptor captor = + ArgumentCaptor.forClass(CACertificateRequestDto.class); + + verify(partnerCertificateManagerService, times(1)) + .uploadCACertificate(captor.capture()); + + CACertificateRequestDto dto = captor.getValue(); + assertEquals("FTM", dto.getPartnerDomain()); + assertEquals(certificateResponse, dto.getCertificateData()); + } + + /** + * ✅ Error In Response → Should Not Upload + */ + @Test + public void handleCACertificate_whenServiceError_shouldNotUpload() throws Exception { + + Map data = new HashMap<>(); + data.put("partnerDomain", "FTM"); + data.put("certChainDatashareUrl", "http://test-url"); + + EventModel eventModel = buildEvent(data); + + String response = "{\"errors\":[{\"errorCode\":\"ERR-001\"}]}"; + + when(restTemplate.getForObject(anyString(), eq(String.class))) + .thenReturn(response); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setErrors(Collections.singletonList(new ServiceError("ERR-001", "Error"))); + + controller.handleCACertificate(eventModel); + + verify(partnerCertificateManagerService, times(1)) + .uploadCACertificate(any()); + } + + /** + * ✅ Domain Not Allowed + */ + @Test + public void handleCACertificate_domainNotAllowed() { + + Map data = new HashMap<>(); + data.put("partnerDomain", "NOT_ALLOWED"); + data.put("certChainDatashareUrl", "http://test-url"); + + EventModel eventModel = buildEvent(data); + + controller.handleCACertificate(eventModel); + + verifyNoInteractions(partnerCertificateManagerService); + } + + /** + * ✅ Missing Keys + */ + @Test + public void handleCACertificate_missingKeys() { + + Map data = new HashMap<>(); + data.put("partnerDomain", "FTM"); + + EventModel eventModel = buildEvent(data); + + controller.handleCACertificate(eventModel); + + verifyNoInteractions(partnerCertificateManagerService); + } + + /** + * ✅ Exception From RestTemplate + */ + @Test + public void handleCACertificate_restTemplateThrowsException() { + + Map data = new HashMap<>(); + data.put("partnerDomain", "FTM"); + data.put("certChainDatashareUrl", "http://test-url"); + + EventModel eventModel = buildEvent(data); + + when(restTemplate.getForObject(anyString(), eq(String.class))) + .thenThrow(new RuntimeException("Network error")); + + assertDoesNotThrow(() -> controller.handleCACertificate(eventModel)); + + verify(partnerCertificateManagerService, never()) + .uploadCACertificate(any()); + } + + /** + * ✅ ObjectMapper Parsing Exception + */ + @Test + public void handleCACertificate_objectMapperThrowsException() throws Exception { + + Map data = new HashMap<>(); + data.put("partnerDomain", "FTM"); + data.put("certChainDatashareUrl", "http://test-url"); + + EventModel eventModel = buildEvent(data); + + String response = "invalid-json"; + + when(restTemplate.getForObject(anyString(), eq(String.class))) + .thenReturn(response); + + controller.handleCACertificate(eventModel); + + verify(partnerCertificateManagerService, times(1)) + .uploadCACertificate(any()); + } + } diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java new file mode 100644 index 00000000000..f268d62997c --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java @@ -0,0 +1,126 @@ +package io.mosip.kernel.syncdata.test.websub; + +import io.mosip.kernel.core.websub.model.EventModel; +import io.mosip.kernel.core.websub.spi.PublisherClient; +import io.mosip.kernel.core.websub.spi.SubscriptionClient; +import io.mosip.kernel.syncdata.websub.PartnerCACertEventSubscriber; +import io.mosip.kernel.websub.api.model.SubscriptionChangeRequest; +import io.mosip.kernel.websub.api.model.SubscriptionChangeResponse; +import io.mosip.kernel.websub.api.model.UnsubscriptionRequest; +import org.junit.jupiter.api.BeforeEach; +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.lang.reflect.Field; +import java.net.http.HttpHeaders; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class PartnerCACertEventSubscriberTest { + + @Mock + private PublisherClient publisherClient; + + @Mock + private SubscriptionClient subscribe; + + @InjectMocks + private PartnerCACertEventSubscriber subscriber; + + @BeforeEach + void setUp() throws Exception { + setField("topicName", "test-topic"); + setField("callbackUrl", "http://callback-url"); + setField("callbackSecret", "secret"); + setField("hubUrl", "http://hub-url"); + setField("publisherUrl", "http://publisher-url"); + } + + private void setField(String fieldName, Object value) throws Exception { + Field field = PartnerCACertEventSubscriber.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(subscriber, value); + } + + /** + * ✅ Test Successful Subscription + */ + @Test + void subscribeTopics_success() { + + subscriber.subscribeTopics(); + + verify(subscribe, times(1)).subscribe(any(SubscriptionChangeRequest.class)); + } + + /** + * ✅ Test Subscription Request Values Are Set Properly + */ + @Test + void subscribeTopics_requestValuesValidation() { + + ArgumentCaptor captor = + ArgumentCaptor.forClass(SubscriptionChangeRequest.class); + + subscriber.subscribeTopics(); + + verify(subscribe).subscribe(captor.capture()); + + SubscriptionChangeRequest request = captor.getValue(); + + assertEquals("test-topic", request.getTopic()); + assertEquals("http://callback-url", request.getCallbackURL()); + assertEquals("secret", request.getSecret()); + assertEquals("http://hub-url", request.getHubURL()); + } + + /** + * ✅ Test Exception During Subscription + */ + @Test + void subscribeTopics_whenExceptionThrown_shouldNotThrow() { + + doThrow(new RuntimeException("Subscription failed")) + .when(subscribe).subscribe(any()); + + assertDoesNotThrow(() -> subscriber.subscribeTopics()); + + verify(subscribe, times(1)).subscribe(any()); + } + + /** + * ✅ Test Multiple Calls (Scheduler Behavior) + */ + @Test + void subscribeTopics_multipleCalls_shouldInvokeEachTime() { + + subscriber.subscribeTopics(); + subscriber.subscribeTopics(); + + verify(subscribe, times(2)).subscribe(any()); + } + + /** + * ✅ Test When Required Fields Are Null + */ + @Test + void subscribeTopics_withNullValues_shouldStillCallSubscribe() throws Exception { + + setField("topicName", null); + setField("callbackUrl", null); + setField("callbackSecret", null); + setField("hubUrl", null); + + subscriber.subscribeTopics(); + + verify(subscribe, times(1)).subscribe(any()); + } +} From e72b6e08bc671f4b9e7865396ee9be8972afde25 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 19:46:15 +0530 Subject: [PATCH 07/19] [MOSIP-42804] - added test case Signed-off-by: Nidhi0201 --- .../helper/ClientSettingsHelperTest.java | 292 ++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/ClientSettingsHelperTest.java diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/ClientSettingsHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/ClientSettingsHelperTest.java new file mode 100644 index 00000000000..aa19ff383af --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/ClientSettingsHelperTest.java @@ -0,0 +1,292 @@ +package io.mosip.kernel.syncdata.test.service.helper; + +import io.mosip.kernel.clientcrypto.constant.ClientType; +import io.mosip.kernel.clientcrypto.dto.TpmCryptoRequestDto; +import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; +import io.mosip.kernel.clientcrypto.service.spi.ClientCryptoManagerService; +import io.mosip.kernel.syncdata.dto.DynamicFieldDto; +import io.mosip.kernel.syncdata.dto.RegistrationCenterMachineDto; +import io.mosip.kernel.syncdata.dto.response.SyncDataBaseDto; +import io.mosip.kernel.syncdata.entity.*; +import io.mosip.kernel.syncdata.repository.ModuleDetailRepository; +import io.mosip.kernel.syncdata.service.helper.ClientSettingsHelper; +import io.mosip.kernel.syncdata.utils.MapperUtils; +import io.mosip.kernel.syncdata.utils.SyncMasterDataServiceHelper; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.core.env.Environment; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ClientSettingsHelperTest { + + @InjectMocks + private ClientSettingsHelper clientSettingsHelper; + + @Mock + private SyncMasterDataServiceHelper serviceHelper; + + @Mock + private ModuleDetailRepository moduleDetailRepository; + + @Mock + private Environment environment; + + @Mock + private MapperUtils mapper; + + @Mock + private ClientCryptoManagerService clientCryptoManagerService; + + private RegistrationCenterMachineDto machineDto; + + @BeforeEach + void setUp() { + ReflectionTestUtils.setField(clientSettingsHelper, "regClientModuleId", "10002"); + ReflectionTestUtils.setField(clientSettingsHelper, "scriptNames", + Set.of("testscript.mvel")); + + machineDto = new RegistrationCenterMachineDto(); + machineDto.setPublicKey("publicKey"); + machineDto.setClientType(ClientType.TPM); + } + + @Test + void testGetInitiateDataFetch_nonV2API() { + + when(serviceHelper.getAppAuthenticationMethodDetails(any(), any())) + .thenReturn(CompletableFuture.completedFuture(List.of())); + + Map result = + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + false, + false, + null + ); + + assertNotNull(result); + assertTrue(result.containsKey(AppAuthenticationMethod.class)); + + verify(serviceHelper, atLeastOnce()) + .getAppAuthenticationMethodDetails(any(), any()); + } + + @Test + void testRetrieveData_structured_v2() throws Exception { + + List data = List.of("test"); + + CompletableFuture> future = + CompletableFuture.completedFuture(data); + + Map futures = new HashMap<>(); + futures.put(Language.class, future); + + List response = + clientSettingsHelper.retrieveData(futures, machineDto, true); + + verify(serviceHelper) + .getSyncDataBaseDtoV2(eq("Language"), + eq("structured"), + eq(data), + eq(machineDto), + anyList()); + } + + @Test + void testRetrieveData_dynamicData() throws Exception { + + DynamicFieldDto dto1 = new DynamicFieldDto(); + dto1.setName("field1"); + + DynamicFieldDto dto2 = new DynamicFieldDto(); + dto2.setName("field1"); + + CompletableFuture> future = + CompletableFuture.completedFuture(List.of(dto1, dto2)); + + Map futures = new HashMap<>(); + futures.put(DynamicFieldDto.class, future); + + clientSettingsHelper.retrieveData(futures, machineDto, false); + + verify(serviceHelper) + .getSyncDataBaseDto(eq("field1"), + eq("dynamic"), + anyList(), + eq(machineDto), + anyList()); + } + + @Test + void testRetrieveData_structuredUrl_encryptionFlow() throws Exception { + + Map urlMap = Map.of("url", "http://test"); + + CompletableFuture> future = + CompletableFuture.completedFuture(urlMap); + + Map futures = new HashMap<>(); + futures.put(Template.class, future); + + when(mapper.getObjectAsJsonString(any())) + .thenReturn("{\"url\":\"http://test\"}"); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("encryptedValue"); + + when(clientCryptoManagerService.csEncrypt(any(TpmCryptoRequestDto.class))) + .thenReturn(cryptoResponse); + + List result = + clientSettingsHelper.retrieveData(futures, machineDto, true); + + assertEquals(1, result.size()); + assertEquals("encryptedValue", result.get(0).getData()); + } + + @Test + void testGetConfiguredScriptUrlDetail() throws Exception { + + when(environment.getProperty(anyString())) + .thenReturn("value"); + + when(mapper.getObjectAsJsonString(any())) + .thenReturn("{json}"); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("encryptedScript"); + + when(clientCryptoManagerService.csEncrypt(any(TpmCryptoRequestDto.class))) + .thenReturn(cryptoResponse); + + List result = + clientSettingsHelper.getConfiguredScriptUrlDetail(machineDto); + + assertEquals(1, result.size()); + assertEquals("script", result.get(0).getEntityType()); + assertEquals("encryptedScript", result.get(0).getData()); + } + + @Test + void testRetrieveData_interruptedException() throws Exception { + + CompletableFuture future = mock(CompletableFuture.class); + when(future.get()).thenThrow(new InterruptedException()); + + Map futures = new HashMap<>(); + futures.put(Language.class, future); + + List result = + clientSettingsHelper.retrieveData(futures, machineDto, true); + + assertNotNull(result); + } + + @Test + void testFullSyncEntity_lastUpdatedNull() { + + when(serviceHelper.getAppAuthenticationMethodDetails(isNull(), any())) + .thenReturn(CompletableFuture.completedFuture(List.of())); + + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + false, + false, + "AppAuthenticationMethod" + ); + + verify(serviceHelper) + .getAppAuthenticationMethodDetails(isNull(), any()); + } + + @Test + void testHasURLDetails_propertyNotPresent() { + + Map result = + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + true, // isV2API + false, + null + ); + + verify(serviceHelper).getTemplates(any(), any(), any()); + } + + @Test + void testHasURLDetails_onlyFullSync_deltaSyncTrue() { + + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + true, + true, // deltaSync = true + null + ); + + verify(serviceHelper).getTemplates(any(), any(), any()); + } + + @Test + void testHasURLDetails_onlyFullSync_deltaSyncFalse() { + + Map result = + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + true, + false, // deltaSync = false + null + ); + + assertNull(result.get(Template.class)); + } + + @Test + void testHasURLDetails_onlyFullSyncFalse() { + + Map result = + clientSettingsHelper.getInitiateDataFetch( + "machine1", + "center1", + LocalDateTime.now(), + LocalDateTime.now(), + true, + true, // deltaSync true + null + ); + + assertNull(result.get(Template.class)); + } +} From 4656e0835f8f55d50723508d841612419285dcfe Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 20:24:10 +0530 Subject: [PATCH 08/19] [MOSIP-42804] - added test case Signed-off-by: Nidhi0201 --- .../helper/IdentitySchemaHelperTest.java | 99 ++++++++++++ .../service/helper/KeymanagerHelperTest.java | 130 ++++++++++++++++ .../SyncJobHelperServiceTest.java | 143 +++++++++++++++++- 3 files changed, 367 insertions(+), 5 deletions(-) create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/IdentitySchemaHelperTest.java create mode 100644 admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/KeymanagerHelperTest.java rename admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/{ => helper}/SyncJobHelperServiceTest.java (67%) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/IdentitySchemaHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/IdentitySchemaHelperTest.java new file mode 100644 index 00000000000..bbccf7d1775 --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/IdentitySchemaHelperTest.java @@ -0,0 +1,99 @@ +package io.mosip.kernel.syncdata.test.service.helper; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.syncdata.constant.MasterDataErrorCode; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.syncdata.service.helper.IdentitySchemaHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.RestTemplate; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class IdentitySchemaHelperTest { + + @InjectMocks + private IdentitySchemaHelper identitySchemaHelper; + + @Mock + private RestTemplate restTemplate; + + @Mock + private ObjectMapper objectMapper; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + + // Set private @Value field via ReflectionTestUtils + ReflectionTestUtils.setField(identitySchemaHelper, "idSchemaUrl", "http://dummy-schema-url"); + } + + @Test + public void testGetLatestIdentitySchema_internalServerError() throws Exception { + // Mock RestTemplate to throw an exception to trigger catch block + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenThrow(new RuntimeException("Connection failed")); + + // Call the method and assert that SyncDataServiceException is thrown + SyncDataServiceException exception = assertThrows(SyncDataServiceException.class, () -> + identitySchemaHelper.getLatestIdentitySchema(LocalDateTime.now(), 1.0, "registration-client", "schema")); + + // Verify error code is SCHEMA_FETCH_FAILED + assertEquals(MasterDataErrorCode.SCHEMA_FETCH_FAILED.getErrorCode(), exception.getErrorCode()); + } + + @Test + public void testGetLatestIdentitySchema_validationError() throws Exception { + // Mock response with errors + ResponseWrapper wrapper = new ResponseWrapper<>(); + ReflectionTestUtils.setField(wrapper, "errors", Collections.singletonList("Some validation error")); + + ResponseEntity responseEntity = ResponseEntity.ok("{}"); + when(restTemplate.getForEntity(any(), eq(String.class))).thenReturn(responseEntity); + when(objectMapper.readValue(eq("{}"), any(TypeReference.class))).thenReturn(wrapper); + + // Expect SyncInvalidArgumentException wrapped in SyncDataServiceException + assertThrows(SyncDataServiceException.class, () -> + identitySchemaHelper.getLatestIdentitySchema(LocalDateTime.now(), 1.0, "domain", "type")); + } + + @Test + public void testGetLatestIdentitySchema_backwardCompatibilityRetain() throws Exception { + // Prepare mock ObjectNode + ObjectNode responseNode = mock(ObjectNode.class); + when(responseNode.retain(any(List.class))).thenReturn(responseNode); + + // Prepare ResponseWrapper with mock response + ResponseWrapper wrapper = new ResponseWrapper<>(); + ReflectionTestUtils.setField(wrapper, "response", responseNode); + + // Mock RestTemplate and ObjectMapper + ResponseEntity responseEntity = ResponseEntity.ok("{}"); + when(restTemplate.getForEntity(any(), eq(String.class))).thenReturn(responseEntity); + when(objectMapper.readValue(eq("{}"), any(TypeReference.class))).thenReturn(wrapper); + + // Call the method with type = "schema" and domain = "registration-client" + ObjectNode result = (ObjectNode) identitySchemaHelper.getLatestIdentitySchema( + LocalDateTime.now(), 1.0, "registration-client", "schema"); + + // Verify retain() was called with the expected properties + List expectedProperties = Arrays.asList("schema", "schemaJson", "id", "idVersion", "effectiveFrom"); + verify(responseNode).retain(expectedProperties); + + // Assert the returned node is the same mock + assertEquals(responseNode, result); + } +} \ No newline at end of file diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/KeymanagerHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/KeymanagerHelperTest.java new file mode 100644 index 00000000000..e4ad6183bb1 --- /dev/null +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/KeymanagerHelperTest.java @@ -0,0 +1,130 @@ +package io.mosip.kernel.syncdata.test.service.helper; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.kernel.core.exception.ServiceError; +import io.mosip.kernel.core.http.ResponseWrapper; +import io.mosip.kernel.signature.dto.JWTSignatureRequestDto; +import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; +import io.mosip.kernel.syncdata.dto.response.KeyPairGenerateResponseDto; +import io.mosip.kernel.syncdata.exception.SyncDataServiceException; +import io.mosip.kernel.syncdata.exception.SyncInvalidArgumentException; +import io.mosip.kernel.syncdata.constant.AdminServiceErrorCode; +import io.mosip.kernel.syncdata.service.helper.KeymanagerHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.RestTemplate; + +import java.util.Collections; +import java.util.Optional; + +public class KeymanagerHelperTest { + + @InjectMocks + private KeymanagerHelper keymanagerHelper; + + @Mock + private RestTemplate restTemplate; + + @Mock + private ObjectMapper objectMapper; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + // Set private @Value fields using ReflectionTestUtils + ReflectionTestUtils.setField(keymanagerHelper, "certificateUrl", "http://dummy-certificate-url"); + ReflectionTestUtils.setField(keymanagerHelper, "signUrl", "http://dummy-sign-url"); + ReflectionTestUtils.setField(keymanagerHelper, "signApplicationid", "KERNEL"); + ReflectionTestUtils.setField(keymanagerHelper, "signRefid", "SIGN"); + } + + @Test + public void testGetCertificate_success() throws Exception { + KeyPairGenerateResponseDto responseDto = new KeyPairGenerateResponseDto(); + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(responseDto); + + String jsonResponse = "{}"; // dummy JSON + ResponseEntity responseEntity = ResponseEntity.ok(jsonResponse); + + when(restTemplate.getForEntity(any(), eq(String.class))).thenReturn(responseEntity); + when(objectMapper.readValue(eq(jsonResponse), any(TypeReference.class))).thenReturn(wrapper); + + KeyPairGenerateResponseDto result = keymanagerHelper.getCertificate("APPID", Optional.of("REFID")); + assertNotNull(result); + assertEquals(responseDto, result); + } + + @Test + public void testGetCertificate_withValidationErrors_shouldThrowSyncDataServiceException() throws Exception { + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setErrors(Collections.singletonList(new ServiceError("ERR001", "Invalid input"))); + + String jsonResponse = "{}"; + ResponseEntity responseEntity = ResponseEntity.ok(jsonResponse); + + when(restTemplate.getForEntity(any(), eq(String.class))).thenReturn(responseEntity); + when(objectMapper.readValue(eq(jsonResponse), any(TypeReference.class))).thenReturn(wrapper); + + SyncDataServiceException exception = assertThrows(SyncDataServiceException.class, () -> + keymanagerHelper.getCertificate("APPID", Optional.empty())); + + assertEquals(AdminServiceErrorCode.VALIDATION_ERROR.getErrorCode(), exception.getErrorCode()); + } + + @Test + public void testGetSignature_success() throws Exception { + String responseBody = "{\"key\":\"value\"}"; + + JWTSignatureResponseDto jwtResponse = new JWTSignatureResponseDto(); + jwtResponse.setJwtSignedData("signedData"); + + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(jwtResponse); + + String jsonResponse = "{}"; + ResponseEntity responseEntity = ResponseEntity.ok(jsonResponse); + + when(restTemplate.postForEntity(any(), any(HttpEntity.class), eq(String.class))).thenReturn(responseEntity); + when(objectMapper.readValue(eq(jsonResponse), any(TypeReference.class))).thenReturn(wrapper); + + String result = keymanagerHelper.getSignature(responseBody); + assertEquals("signedData", result); + } + + @Test + public void testGetFileSignature_success() throws Exception { + KeymanagerHelper helperSpy = spy(keymanagerHelper); + doReturn("signedHash").when(helperSpy).getSignature(any()); + + String result = helperSpy.getFileSignature("hashValue"); + assertEquals("signedHash", result); + + verify(helperSpy).getSignature("{\"hash\":\"hashValue\"}"); + } + + @Test + public void testGetCertificate_internalServerError() throws Exception { + // Mock RestTemplate to throw an exception + when(restTemplate.getForEntity(any(), eq(String.class))) + .thenThrow(new RuntimeException("Connection failed")); + + // Call the method and assert that SyncDataServiceException is thrown + SyncDataServiceException exception = assertThrows(SyncDataServiceException.class, () -> + keymanagerHelper.getCertificate("APPID", Optional.of("REFID"))); + + // Verify the error code is INTERNAL_SERVER_ERROR + assertEquals(AdminServiceErrorCode.INTERNAL_SERVER_ERROR.getErrorCode(), exception.getErrorCode()); + } +} diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncJobHelperServiceTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java similarity index 67% rename from admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncJobHelperServiceTest.java rename to admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java index ac84fdb877d..2e5a0a2ba09 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncJobHelperServiceTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java @@ -1,4 +1,4 @@ -package io.mosip.kernel.syncdata.test.service; +package io.mosip.kernel.syncdata.test.service.helper; import io.mosip.kernel.syncdata.dto.BlacklistedWordsDto; import io.mosip.kernel.syncdata.dto.DynamicFieldDto; @@ -7,6 +7,7 @@ import io.mosip.kernel.syncdata.utils.MapperUtils; import io.mosip.kernel.syncdata.utils.SyncMasterDataServiceHelper; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -15,14 +16,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import static org.mockito.Mockito.*; @@ -43,6 +44,16 @@ public class SyncJobHelperServiceTest { @InjectMocks private SyncJobHelperService syncJobHelperService; + private Path tempDir; + + @Before + public void setup() throws Exception { + tempDir = Files.createTempDirectory("snapshot-test"); + ReflectionTestUtils.setField(syncJobHelperService, "clientSettingsDir", tempDir.toString()); + ReflectionTestUtils.setField(syncJobHelperService, "regClientModuleId", "10002"); + ReflectionTestUtils.setField(syncJobHelperService, "deltaCacheEvictCron", "0 0/15 * * * *"); + } + @Test public void testEvictDeltaCaches_Success() { Cache cache = mock(Cache.class); @@ -176,4 +187,126 @@ public void testClearCacheAndRecreateSnapshot_ServiceCallException() throws Exce verify(cacheManager, never()).getCache("delta-sync"); } + // =============================== + // Cache Eviction Tests + // =============================== + + @Test + public void testEvictDeltaCaches_success() { + Cache cache = mock(Cache.class); + when(cacheManager.getCache("delta-sync")).thenReturn(cache); + + syncJobHelperService.evictDeltaCaches(); + + verify(cache).clear(); + } + + // =============================== + // Timestamp Tests + // =============================== + + @Test + public void testGetFullSyncCurrentTimestamp() { + LocalDateTime result = syncJobHelperService.getFullSyncCurrentTimestamp(); + Assert.assertEquals(0, result.getHour()); + Assert.assertEquals(0, result.getMinute()); + Assert.assertEquals(0, result.getSecond()); + } + + @Test + public void testGetDeltaSyncCurrentTimestamp_validCron() { + LocalDateTime result = syncJobHelperService.getDeltaSyncCurrentTimestamp(); + Assert.assertNotNull(result); + } + + @Test + public void testGetDeltaSyncCurrentTimestamp_invalidCron() { + ReflectionTestUtils.setField(syncJobHelperService, "deltaCacheEvictCron", "invalid"); + try { + syncJobHelperService.getDeltaSyncCurrentTimestamp(); + Assert.fail(); + } catch (Exception ignored) { + } + } + + // =============================== + // Snapshot Creation Tests + // =============================== + + @Test + public void testCreateEntitySnapshot_success() { + + List list = new ArrayList<>(); + CompletableFuture> future = + CompletableFuture.completedFuture(list); + + // mock all other service calls to return empty future + mockAllServiceCalls(); + + syncJobHelperService.createEntitySnapshot(); + } + + @Test + public void testCreateEntitySnapshot_completionException() { + + CompletableFuture future = mock(CompletableFuture.class); + + when(serviceHelper.getAppAuthenticationMethodDetails(any(), any())) + .thenReturn(future); + + try { + syncJobHelperService.createEntitySnapshot(); + Assert.fail(); + } catch (Exception ignored) { + } + } + + @Test + public void testDynamicFieldHandling() { + + DynamicFieldDto dto1 = new DynamicFieldDto(); + dto1.setName("field1"); + + DynamicFieldDto dto2 = new DynamicFieldDto(); + dto2.setName("field1"); + + List list = Arrays.asList(dto1, dto2); + + CompletableFuture> future = + CompletableFuture.completedFuture(list); + + when(serviceHelper.getAllDynamicFields(any(), any())) + .thenReturn(future); + + mockAllServiceCalls(); + + syncJobHelperService.createEntitySnapshot(); + } + + // =============================== + // Helper + // =============================== + + private void mockAllServiceCalls() { + + CompletableFuture empty = CompletableFuture.completedFuture(new ArrayList<>()); + + lenient().when(serviceHelper.getAppAuthenticationMethodDetails(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getAppRolePriorityDetails(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getTemplates(anyString(), any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getDocumentTypes(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getApplicantValidDocument(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getLocationHierarchy(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getLocationHierarchyList(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getAllDynamicFields(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getReasonCategory(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getReasonList(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getScreenAuthorizationDetails(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getScreenDetails(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getBlackListedWords(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getProcessList(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getSyncJobDefDetails(any(), any())).thenReturn(empty); + lenient().when(serviceHelper.getPermittedConfig(any(), any())).thenReturn(empty); + } + } From cdd457242dcbffb13dae4fbcbe3f5cdd371fd951 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 20:47:26 +0530 Subject: [PATCH 09/19] [MOSIP-42804] - added test case Signed-off-by: Nidhi0201 --- .../impl/SyncAuthTokenServiceImplTest.java | 100 +++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java index 200ebb46ef5..85bcd9c9aa3 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java @@ -32,9 +32,7 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.Base64; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -138,6 +136,101 @@ void getAuthToken_emptyTokenResponse_throwsRequestException() throws Exception { } + // ======================= SUCCESS ======================= + @Test + void getAuthToken_emptyTokenResponse() throws Exception { + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + // Create JWT-like token + String headerJson = "{\"kid\":\"KEY1\"}"; + String payloadJson = "{\"machineName\":\"machine1\",\"userId\":\"user1\",\"password\":\"pass123\",\"timestamp\":\"" + now + "\",\"authType\":\"OTP\"}"; + String token = Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString("sig".getBytes()); + + // 1️⃣ Mock machineRepository to return the machine (used in validateRequestData) + when(machineRepository.findBySignKeyIndex("KEY1")).thenReturn(List.of(machine)); + + // 2️⃣ Force validateSignature = true + when(clientCryptoFacade.validateSignature(any(), any(), any(), any())).thenReturn(true); + + // 3️⃣ Mock payload to MachineAuthDto + when(objectMapper.readValue(any(byte[].class), eq(MachineAuthDto.class))) + .thenReturn(new MachineAuthDto() {{ + setMachineName("machine1"); + setUserId("user1"); + setPassword("pass123"); + setAuthType("OTP"); + setTimestamp(now); + }}); + + // 4️⃣ Mock REST call inside getTokenResponseDTO + String fakeResponse = "{\"response\":{}}"; // minimal valid JSON + when(restTemplate.postForEntity(any(), any(), eq(String.class))) + .thenReturn(ResponseEntity.ok(fakeResponse)); + + // 5️⃣ Mock ObjectMapper.readValue to convert fake response + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(new TokenResponseDto()); + when(objectMapper.readValue(eq(fakeResponse), any(TypeReference.class))).thenReturn(wrapper); + + // 6️⃣ Mock encryption + when(cryptomanagerUtils.decodeBase64Data(anyString())).thenReturn("decoded".getBytes()); + + // Call public method + assertThrows(RequestException.class, () -> { + service.getAuthToken(token); + }); + + } + + @Test + void getAuthToken_whenTokenResponseIsEmpty_thenThrowsRequestException() throws Exception { + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + + // Create JWT-like token + String headerJson = "{\"kid\":\"KEY1\"}"; + String payloadJson = "{\"machineName\":\"machine1\",\"userId\":\"user1\",\"password\":\"pass123\",\"timestamp\":\"" + now + "\",\"authType\":\"OTP\"}"; + String token = Base64.getUrlEncoder().encodeToString(headerJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString(payloadJson.getBytes()) + "." + + Base64.getUrlEncoder().encodeToString("sig".getBytes()); + + // 1️⃣ Mock machineRepository to return the machine (used in validateRequestData) + when(machineRepository.findBySignKeyIndex("KEY1")).thenReturn(List.of(machine)); + + // 2️⃣ Force validateSignature = true + when(clientCryptoFacade.validateSignature(any(), any(), any(), any())).thenReturn(true); + + // 3️⃣ Mock payload to MachineAuthDto + when(objectMapper.readValue(any(byte[].class), eq(MachineAuthDto.class))) + .thenReturn(new MachineAuthDto() {{ + setMachineName("machine1"); + setUserId("user1"); + setPassword("pass123"); + setAuthType("REFRESH"); + setTimestamp(now); + }}); + + // 4️⃣ Mock REST call inside getTokenResponseDTO + String fakeResponse = "{\"response\":{}}"; // minimal valid JSON + when(restTemplate.postForEntity(any(), any(), eq(String.class))) + .thenReturn(ResponseEntity.ok(fakeResponse)); + + // 5️⃣ Mock ObjectMapper.readValue to convert fake response + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setResponse(new TokenResponseDto()); + when(objectMapper.readValue(eq(fakeResponse), any(TypeReference.class))).thenReturn(wrapper); + + // 6️⃣ Mock encryption + when(cryptomanagerUtils.decodeBase64Data(anyString())).thenReturn("decoded".getBytes()); + + // Call public method + assertThrows(RequestException.class, () -> { + service.getAuthToken(token); + }); + + } + // ===================================================== // TIMESTAMP VALIDATION // ===================================================== @@ -234,4 +327,5 @@ void validateRequestData_invalidSignature() { "{}".getBytes(), "sig".getBytes())); } + } From 1c1ad2955e6ca268b0ec70f252a0dcaef6fc6fe6 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 20:50:17 +0530 Subject: [PATCH 10/19] [MOSIP-42804] - added test case Signed-off-by: Nidhi0201 --- .../test/service/helper/SyncJobHelperServiceTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java index 2e5a0a2ba09..0f1fe9f9a6f 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/helper/SyncJobHelperServiceTest.java @@ -23,7 +23,11 @@ import java.nio.file.Path; import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Arrays; import java.util.concurrent.CompletableFuture; import static org.mockito.Mockito.*; From 21137d85dbcd2fde02636a25898279d064f4c652 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 24 Feb 2026 20:56:44 +0530 Subject: [PATCH 11/19] [MOSIP-42804] - coderabbit comment fix Signed-off-by: Nidhi0201 --- .../test/controller/WebsubCallbackControllerTest.java | 2 +- .../test/websub/PartnerCACertEventSubscriberTest.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java index 8f8cc022b71..fad72b7332a 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java @@ -247,7 +247,7 @@ public void handleCACertificate_success() throws Exception { * ✅ Error In Response → Should Not Upload */ @Test - public void handleCACertificate_whenServiceError_shouldNotUpload() throws Exception { + public void handleCACertificate_whenServiceError_shouldStillUpload() throws Exception { Map data = new HashMap<>(); data.put("partnerDomain", "FTM"); diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java index f268d62997c..b8400919829 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/websub/PartnerCACertEventSubscriberTest.java @@ -24,9 +24,6 @@ @ExtendWith(MockitoExtension.class) class PartnerCACertEventSubscriberTest { - @Mock - private PublisherClient publisherClient; - @Mock private SubscriptionClient Date: Tue, 24 Feb 2026 21:03:43 +0530 Subject: [PATCH 12/19] [MOSIP-42804] - coderabbit comment fix Signed-off-by: Nidhi0201 --- .../syncdata/test/controller/WebsubCallbackControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java index fad72b7332a..021d2ed991d 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/controller/WebsubCallbackControllerTest.java @@ -327,7 +327,7 @@ public void handleCACertificate_restTemplateThrowsException() { * ✅ ObjectMapper Parsing Exception */ @Test - public void handleCACertificate_objectMapperThrowsException() throws Exception { + public void handleCACertificate_whenInvalidJsonResponse_shouldStillUpload() throws Exception { Map data = new HashMap<>(); data.put("partnerDomain", "FTM"); From a1820dca3c7475616c6205209f98b1da95c905c8 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Wed, 25 Feb 2026 19:18:39 +0530 Subject: [PATCH 13/19] MOSIP-42804: Move SyncMasterDataServiceHelperTest to util package Signed-off-by: Nidhi0201 --- .../{service => utils}/SyncMasterDataServiceHelperTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/{service => utils}/SyncMasterDataServiceHelperTest.java (99%) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java similarity index 99% rename from admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java rename to admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java index da9d0ac718d..9baaa8eb8b8 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java @@ -1,4 +1,4 @@ -package io.mosip.kernel.syncdata.test.service; +package io.mosip.kernel.syncdata.test.utils; import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.kernel.syncdata.entity.id.ApplicantValidDocumentID; From 7a776be8a46b7e53c8f4dd57091aa4762aaa73c8 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Wed, 25 Feb 2026 19:57:47 +0530 Subject: [PATCH 14/19] MOSIP-42804: RestHelper coverage added Signed-off-by: Nidhi0201 --- .../mosip/hotlist/helper/RestHelperTest.java | 141 +++++++++++++++++- 1 file changed, 137 insertions(+), 4 deletions(-) diff --git a/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java b/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java index fdccc3fb855..bfd0a33e3d4 100644 --- a/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java +++ b/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java @@ -1,5 +1,6 @@ package io.mosip.hotlist.helper; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.mosip.hotlist.constant.HotlistErrorConstants; @@ -20,6 +21,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.LinkedMultiValueMap; @@ -31,13 +33,11 @@ import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @@ -434,4 +434,137 @@ public void testCheckErrorResponseRetry() throws JsonParseException, JsonMapping assertEquals(cause.getErrorText(), HotlistErrorConstants.CLIENT_ERROR.getErrorMessage()); } } + + @Test + public void testRequestSyncSuccess() throws Exception { + + RestRequestDTO dto = new RestRequestDTO(); + dto.setUri("http://test.com"); + dto.setHttpMethod(HttpMethod.GET); + dto.setResponseType(ObjectNode.class); + + ReflectionTestUtils.setField(restHelper, "mapper", new ObjectMapper()); + ReflectionTestUtils.setField(restHelper, "webClient", webClient); + + String jsonResponse = "{\"response\":{\"status\":\"success\"}}"; + + when(webClient.method(HttpMethod.GET)).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri("http://test.com")).thenReturn(requestBodySpec); + when(requestBodySpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.bodyToMono(ObjectNode.class)) + .thenReturn(Mono.just(new ObjectMapper().readValue(jsonResponse, ObjectNode.class))); + + ObjectNode response = restHelper.requestSync(dto); + + assertNotNull(response); + assertTrue(response.has("response")); + } + + @Test + public void testRequestAsyncSuccess() { + + RestRequestDTO dto = new RestRequestDTO(); + dto.setUri("http://test.com"); + dto.setHttpMethod(HttpMethod.GET); + dto.setResponseType(String.class); + + when(webClient.method(HttpMethod.GET)).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri("http://test.com")).thenReturn(requestBodySpec); + when(requestBodySpec.retrieve()).thenReturn(responseSpec); + when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just("ASYNC_OK")); + + ReflectionTestUtils.setField(restHelper, "webClient", webClient); + + Object result = restHelper.requestAsync(dto).get(); + + assertEquals("ASYNC_OK", result); + } + + @Test(expected = RestServiceException.class) + public void testRequestSync_WebClientResponseException() throws Exception { + + RestRequestDTO dto = new RestRequestDTO(); + dto.setUri("http://test.com"); + dto.setHttpMethod(HttpMethod.GET); + dto.setResponseType(ObjectNode.class); + + ReflectionTestUtils.setField(restHelper, "mapper", new ObjectMapper()); + ReflectionTestUtils.setField(restHelper, "webClient", webClient); + + when(webClient.method(HttpMethod.GET)).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri("http://test.com")).thenReturn(requestBodySpec); + when(requestBodySpec.retrieve()).thenReturn(responseSpec); + + String errorBody = "{\"errors\":[{\"errorCode\":\"ERR-001\",\"message\":\"Bad Request\"}]}"; + + when(responseSpec.bodyToMono(ObjectNode.class)) + .thenReturn(Mono.error( + new WebClientResponseException( + "Bad Request", + 400, + "Bad Request", + null, + errorBody.getBytes(), + null))); + + restHelper.requestSync(dto); + } + + @Test + public void testRequestSync_WithHeadersAndBody() throws Exception { + + RestRequestDTO dto = new RestRequestDTO(); + dto.setUri("http://test.com"); + dto.setHttpMethod(HttpMethod.POST); + dto.setResponseType(ObjectNode.class); + + // ✅ Use HttpHeaders (IMPORTANT) + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Type", "application/json"); + dto.setHeaders(headers); + + dto.setRequestBody("{\"name\":\"test\"}"); + + ReflectionTestUtils.setField(restHelper, "mapper", new ObjectMapper()); + ReflectionTestUtils.setField(restHelper, "webClient", webClient); + + when(webClient.method(HttpMethod.POST)).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri("http://test.com")).thenReturn(requestBodySpec); + + when(requestBodySpec.headers(any())).thenReturn(requestBodySpec); + when(requestBodySpec.syncBody(any())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.retrieve()).thenReturn(responseSpec); + + ObjectNode node = new ObjectMapper() + .readValue("{\"response\":\"ok\"}", ObjectNode.class); + + when(responseSpec.bodyToMono(ObjectNode.class)) + .thenReturn(Mono.just(node)); + + ObjectNode response = restHelper.requestSync(dto); + + assertNotNull(response); + verify(requestBodySpec).headers(any()); + verify(requestBodySpec).syncBody(any()); + } + + @Test + public void testCheckErrorResponse_ResponseHasErrors_ThrowsClientError() throws Exception { + // Arrange + RestRequestDTO dto = new RestRequestDTO(); + dto.setUri("http://dummy.com"); + dto.setHttpMethod(HttpMethod.GET); + dto.setResponseType(ObjectNode.class); + + String json = "{\"errors\":[{\"errorCode\":\"ERR-001\",\"message\":\"some error\"}]}"; + ObjectMapper realMapper = new ObjectMapper(); + Object response = realMapper.readValue(json, Object.class); + + ReflectionTestUtils.setField(restHelper, "mapper", realMapper); + + // Act & Assert + assertThrows(UndeclaredThrowableException.class, () -> { + ReflectionTestUtils.invokeMethod(restHelper, "checkErrorResponse", response, ObjectNode.class); + }); + } } \ No newline at end of file From c48bb55ce97bafb5bc7049be07a627df38636379 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Wed, 25 Feb 2026 19:59:32 +0530 Subject: [PATCH 15/19] MOSIP-42804: RestHelper coverage added Signed-off-by: Nidhi0201 --- .../test/java/io/mosip/hotlist/helper/RestHelperTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java b/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java index bfd0a33e3d4..c59368bec20 100644 --- a/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java +++ b/admin/hotlist-service/src/test/java/io/mosip/hotlist/helper/RestHelperTest.java @@ -1,6 +1,5 @@ package io.mosip.hotlist.helper; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.mosip.hotlist.constant.HotlistErrorConstants; @@ -33,7 +32,10 @@ import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; From a9018128f9523058579c95104a481e425be1f970 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Wed, 25 Feb 2026 20:51:34 +0530 Subject: [PATCH 16/19] MOSIP-42804: coverage added for SyncMasterDataServiceHelper Signed-off-by: Nidhi0201 --- .../SyncMasterDataServiceHelperTest.java | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java index 9baaa8eb8b8..519d85ea8bc 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java @@ -1,12 +1,18 @@ package io.mosip.kernel.syncdata.test.utils; import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto; +import io.mosip.kernel.clientcrypto.service.spi.ClientCryptoManagerService; +import io.mosip.kernel.syncdata.constant.MasterDataErrorCode; +import io.mosip.kernel.syncdata.dto.response.SyncDataBaseDto; import io.mosip.kernel.syncdata.entity.id.ApplicantValidDocumentID; import io.mosip.kernel.syncdata.entity.id.HolidayID; import io.mosip.kernel.syncdata.exception.AdminServiceException; +import io.mosip.kernel.syncdata.exception.RequestException; import io.mosip.kernel.syncdata.exception.SyncDataServiceException; import io.mosip.kernel.syncdata.exception.SyncServiceException; import org.mockito.InjectMocks; +import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.http.HttpStatus; import io.mosip.kernel.clientcrypto.constant.ClientType; @@ -43,17 +49,20 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.client.RestTemplate; +import java.net.URI; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Arrays; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -181,6 +190,8 @@ public class SyncMasterDataServiceHelperTest { private static LocationHierarchyLevelResponseDto locationHierarchyLevelResponseDto; + private RegistrationCenterMachineDto registrationCenterMachineDto; + @Before public void setUp() { //it is important to ignore the order as its completely async during client settings sync @@ -242,6 +253,12 @@ public void setUp() { ReflectionTestUtils.setField(realHelper, "holidayRepository", holidayRepository); ReflectionTestUtils.setField(realHelper, "blocklistedWordsRepository", blocklistedWordsRepository); ReflectionTestUtils.setField(realHelper, "locationRepository", locationRepository); + + registrationCenterMachineDto = new RegistrationCenterMachineDto(); + registrationCenterMachineDto.setMachineId("M1"); + registrationCenterMachineDto.setPublicKey("PUBLIC_KEY_SAMPLE"); + registrationCenterMachineDto.setMachineSpecId("SPEC1"); + registrationCenterMachineDto.setClientType(ClientType.TPM); } @Test @@ -4714,4 +4731,273 @@ public void testGetLanguageList_DataAccessException() throws Throwable { } } + @Test + public void testGetRegistrationCenterMachine_machineNotFound() { + String keyIndex = "KEY1"; + when(machineRepository.findOneByKeyIndexIgnoreCase(keyIndex)).thenReturn(null); + + RequestException exception = assertThrows(RequestException.class, + () -> realHelper.getRegistrationCenterMachine("RC1", keyIndex)); + assertEquals(MasterDataErrorCode.MACHINE_NOT_FOUND.getErrorCode(), exception.getErrorCode()); + } + + @Test + public void testGetRegistrationCenterMachine_registrationCenterNotFound() { + Machine machine = new Machine(); + machine.setRegCenterId(null); + when(machineRepository.findOneByKeyIndexIgnoreCase("KEY2")).thenReturn(machine); + + RequestException exception = assertThrows(RequestException.class, + () -> realHelper.getRegistrationCenterMachine("RC1", "KEY2")); + assertEquals(MasterDataErrorCode.REGISTRATION_CENTER_NOT_FOUND.getErrorCode(), exception.getErrorCode()); + } + + @Test + public void testGetRegistrationCenterMachine_registrationCenterMismatch() { + Machine machine = new Machine(); + machine.setRegCenterId("RC2"); + when(machineRepository.findOneByKeyIndexIgnoreCase("KEY3")).thenReturn(machine); + + RequestException exception = assertThrows(RequestException.class, + () -> realHelper.getRegistrationCenterMachine("RC1", "KEY3")); + assertEquals(MasterDataErrorCode.REG_CENTER_UPDATED.getErrorCode(), exception.getErrorCode()); + } + + @Test + public void testGetRegistrationCenterMachine_success() throws SyncDataServiceException { + Machine machine = new Machine(); + machine.setId("M1"); + machine.setRegCenterId("RC1"); + machine.setPublicKey("PUBKEY"); + machine.setMachineSpecId("SPEC1"); + + MachineSpecification spec = new MachineSpecification(); + spec.setMachineTypeCode("TYPE1"); + machine.setMachineSpecification(spec); + + when(machineRepository.findOneByKeyIndexIgnoreCase("KEY4")).thenReturn(machine); + + RegistrationCenterMachineDto dto = realHelper.getRegistrationCenterMachine("RC1", "KEY4"); + + assertNotNull(dto); + assertEquals("M1", dto.getMachineId()); + assertEquals("PUBKEY", dto.getPublicKey()); + assertEquals("SPEC1", dto.getMachineSpecId()); + } + + @Test + public void testGetRegistrationCenterMachine_machineSpecNull() throws SyncDataServiceException { + Machine machine = new Machine(); + machine.setId("M2"); + machine.setRegCenterId("RC1"); + machine.setPublicKey("PUBKEY"); + machine.setMachineSpecId("SPEC2"); + machine.setMachineSpecification(null); + + when(machineRepository.findOneByKeyIndexIgnoreCase("KEY5")).thenReturn(machine); + + RegistrationCenterMachineDto dto = realHelper.getRegistrationCenterMachine("RC1", "KEY5"); + + assertNotNull(dto); + } + + @Test + public void testGetRegistrationCenterMachine_dataAccessException() { + when(machineRepository.findOneByKeyIndexIgnoreCase("KEY6")) + .thenThrow(new DataAccessException("DB error") {}); + + SyncDataServiceException exception = assertThrows(SyncDataServiceException.class, + () -> realHelper.getRegistrationCenterMachine("RC1", "KEY6")); + + assertEquals(MasterDataErrorCode.REG_CENTER_MACHINE_FETCH_EXCEPTION.getErrorCode(), + exception.getErrorCode()); + } + + @Test + public void testGetSyncDataBaseDtoV2_entitiesNull() { + List result = new ArrayList<>(); + realHelper.getSyncDataBaseDtoV2("entityName", "entityType", null, + registrationCenterMachineDto, result); + + assertTrue(result.isEmpty()); + } + + @Test + public void testGetSyncDataBaseDtoV2_entitiesAllNull() { + List entities = Arrays.asList(null, null); + List result = new ArrayList<>(); + realHelper.getSyncDataBaseDtoV2("entityName", "entityType", entities, + registrationCenterMachineDto, result); + + assertTrue(result.isEmpty()); + } + + @Test + public void testGetSyncDataBaseDtoV2_success() throws Exception { + List entities = Arrays.asList("val1", "val2"); + List result = new ArrayList<>(); + + // Mock crypto service + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("ENCRYPTED_DATA"); + realHelper.getSyncDataBaseDtoV2("entityName", "entityType", entities, + registrationCenterMachineDto, result); + + assertEquals(0, result.size()); + } + + @Test + public void testGetSyncDataBaseDtoV2_mapperThrowsException() throws Exception { + List entities = Arrays.asList("val1"); + List result = new ArrayList<>(); + + // Should catch exception and result remains empty + realHelper.getSyncDataBaseDtoV2("entityName", "entityType", entities, + registrationCenterMachineDto, result); + + assertTrue(result.isEmpty()); + } + + @Test + public void testGetSyncDataBaseDto_entitiesNull() { + List result = new ArrayList<>(); + realHelper.getSyncDataBaseDto("entityName", "entityType", null, + registrationCenterMachineDto, result); + + assertTrue(result.isEmpty()); + } + + @Test + public void testGetSyncDataBaseDto_entitiesAllNull() { + List entities = Arrays.asList(null, null); + List result = new ArrayList<>(); + realHelper.getSyncDataBaseDto("entityName", "entityType", entities, + registrationCenterMachineDto, result); + + assertTrue(result.isEmpty()); + } + + @Test + public void testGetSyncDataBaseDto_blocklistedWords() throws Exception { + List entities = Arrays.asList("val1"); + List result = new ArrayList<>(); + + realHelper.getSyncDataBaseDto(BlocklistedWords.class.getSimpleName(), "entityType", + entities, registrationCenterMachineDto, result); + + assertEquals(0, result.size()); + } + + @Test + public void testGetSyncDataBaseDto_mapperThrowsPerEntity() { + List entities = Arrays.asList("val1", "val2"); + List result = new ArrayList<>(); + + TpmCryptoResponseDto cryptoResponse = new TpmCryptoResponseDto(); + cryptoResponse.setValue("ENCRYPTED_DATA"); + + realHelper.getSyncDataBaseDto("entityName", "entityType", entities, + registrationCenterMachineDto, result); + + assertEquals(0, result.size()); + } + + @Test + public void testGetAllDynamicFields_success() throws Exception { + + ReflectionTestUtils.setField(realHelper, "dynamicfieldUrl", "http://localhost/dynamic-fields"); + // --- Prepare mock dynamic fields --- + DynamicFieldDto field1 = new DynamicFieldDto(); + field1.setId("f1"); + field1.setName("Field1"); + + DynamicFieldDto field2 = new DynamicFieldDto(); + field2.setId("f2"); + field2.setName("Field2"); + + // --- Prepare paged responses as JSON --- + String resp0Json = "{ \"response\": { \"data\": [ {\"id\": \"f1\", \"name\": \"Field1\"} ], \"totalPages\": 2 } }"; + String resp1Json = "{ \"response\": { \"data\": [ {\"id\": \"f2\", \"name\": \"Field2\"} ], \"totalPages\": 2 } }"; + + doReturn(new ResponseEntity<>(resp1Json, HttpStatus.OK)) + .when(restTemplate).getForEntity(any(URI.class), eq(String.class)); + + // --- Call the async method --- + CompletableFuture> future = realHelper.getAllDynamicFields(null, restTemplate); + + // Wait for completion + List result = future.get(); + + // --- Assertions --- + assertEquals(2, result.size()); + assertEquals("f2", result.get(0).getId()); + assertEquals("Field2", result.get(0).getName()); + } + + @Test + public void testGetAllDynamicFields_WithLastUpdated_ShouldSuccess() throws Exception { + // --- Step 1: Set the dynamicfieldUrl in the helper --- + ReflectionTestUtils.setField(realHelper, "dynamicfieldUrl", "http://localhost/dynamic-fields"); + realHelper = new SyncMasterDataServiceHelper(); + + // Inject the mock RestTemplate + ReflectionTestUtils.setField(realHelper, "restTemplate", restTemplate); + + // Inject dynamicfieldUrl (cannot be null) + ReflectionTestUtils.setField(realHelper, "dynamicfieldUrl", "http://localhost/dynamic-fields"); + + // Inject ObjectMapper + ReflectionTestUtils.setField(realHelper, "objectMapper", new ObjectMapper()); + + // --- Step 2: Prepare mock dynamic fields --- + DynamicFieldDto field1 = new DynamicFieldDto(); + field1.setId("f1"); + field1.setName("Field1"); + + DynamicFieldDto field2 = new DynamicFieldDto(); + field2.setId("f2"); + field2.setName("Field2"); + + // --- Step 3: Prepare paged responses --- + PageDto page0 = new PageDto<>(); + page0.setData(Collections.singletonList(field1)); + page0.setTotalPages(2); + page0.setPageNo(0); + + PageDto page1 = new PageDto<>(); + page1.setData(Collections.singletonList(field2)); + page1.setTotalPages(2); + page1.setPageNo(1); + + ResponseWrapper> resp0 = new ResponseWrapper<>(); + resp0.setResponse(page0); + + ResponseWrapper> resp1 = new ResponseWrapper<>(); + resp1.setResponse(page1); + + // --- Step 4: Mock RestTemplate calls --- + doReturn(new ResponseEntity<>("{\"response\":{\"data\":[{\"id\":\"f1\",\"name\":\"Field1\"}],\"totalPages\":2}}", HttpStatus.OK)) + .doReturn(new ResponseEntity<>("{\"response\":{\"data\":[{\"id\":\"f2\",\"name\":\"Field2\"}],\"totalPages\":2}}", HttpStatus.OK)) + .when(restTemplate).getForEntity(any(URI.class), eq(String.class)); + + // --- Step 5: Call the async method --- + CompletableFuture> future = realHelper.getAllDynamicFields(null); + List result = future.get(); // block until completion + + // --- Step 6: Assertions --- + assertEquals(2, result.size()); + assertEquals("f1", result.get(0).getId()); + assertEquals("Field1", result.get(0).getName()); + assertEquals("f2", result.get(1).getId()); + assertEquals("Field2", result.get(1).getName()); + } + + @Test(expected = SyncDataServiceException.class) + public void testGetAllDynamicFields_restTemplateException() throws Exception { + // Set the dynamicfieldUrl + ReflectionTestUtils.setField(realHelper, "dynamicfieldUrl", "http://localhost/dynamic-fields"); + + // Call the method (should throw SyncDataServiceException) + realHelper.getAllDynamicFields(null).get(); + } } From e2c9150bd6c85b2deba066694fc3e1288e1698e5 Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Thu, 26 Feb 2026 11:51:29 +0530 Subject: [PATCH 17/19] MOSIP-42804: code rabbit comment fix Signed-off-by: Nidhi0201 --- .../test/service/impl/SyncAuthTokenServiceImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java index 85bcd9c9aa3..d8488754c3f 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/service/impl/SyncAuthTokenServiceImplTest.java @@ -90,7 +90,7 @@ void getAuthToken_invalidRequest_throwsRequestException() { // ======================= SUCCESS ======================= @Test - void getAuthToken_emptyTokenResponse_throwsRequestException() throws Exception { + void getAuthToken_invalidTimestamp_throwsRequestException() throws Exception { LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); // Create JWT-like token From f9f4930600904378b961e75b90abb73ae661569e Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Mon, 2 Mar 2026 13:47:53 +0530 Subject: [PATCH 18/19] MOSIP-42804: code rabbit comment fix Signed-off-by: Nidhi0201 --- .../test/service/impl/CacheManagementServiceImplTest.java | 1 + .../syncdata/test/utils/SyncMasterDataServiceHelperTest.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java index 693d45eade0..bf96920ccf3 100644 --- a/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java +++ b/admin/kernel-masterdata-service/src/test/java/io/mosip/kernel/masterdata/test/service/impl/CacheManagementServiceImplTest.java @@ -43,6 +43,7 @@ void clearCacheByCacheName_existingCache_clearsOnlyMatched() { cacheService.clearCacheByCacheName(CacheName.BLOCK_LISTED_WORDS); + verify(mockCache1).clear(); verify(mockCache2, never()).clear(); } diff --git a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java index 519d85ea8bc..5f51b945206 100644 --- a/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java +++ b/admin/kernel-syncdata-service/src/test/java/io/mosip/kernel/syncdata/test/utils/SyncMasterDataServiceHelperTest.java @@ -2598,7 +2598,7 @@ public void testGetTemplates_LastUpdatedNull_ShouldSetEpoch() throws Exception { .findAllLatestCreatedUpdateDeletedByModule(any(), any(), eq("REG")); } - @Test(expected = SyncDataServiceException.class) + @Test public void testGetTemplates_DataAccessException_ShouldThrowSyncDataServiceException() { LocalDateTime lastUpdated = LocalDateTime.now().minusDays(1); @@ -2617,7 +2617,8 @@ public void testGetTemplates_DataAccessException_ShouldThrowSyncDataServiceExcep any(), any(), any())) .thenThrow(new DataAccessResourceFailureException("DB Error")); - syncMasterData.getTemplates("REG", lastUpdated, currentTime); + assertThrows(SyncDataServiceException.class, + () -> syncMasterData.getTemplates("REG", lastUpdated, currentTime)); } @Test From 9d2dd4311f85f3b0d651f707afda90876a6fb4ec Mon Sep 17 00:00:00 2001 From: Nidhi0201 Date: Tue, 3 Mar 2026 15:39:31 +0530 Subject: [PATCH 19/19] MOSIP-42804: review comment resolved Signed-off-by: Nidhi0201 --- .../kernel/syncdata/utils/SyncMasterDataServiceHelper.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java b/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java index aeaf2973e88..797326e8523 100644 --- a/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java +++ b/admin/kernel-syncdata-service/src/main/java/io/mosip/kernel/syncdata/utils/SyncMasterDataServiceHelper.java @@ -2,11 +2,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import io.mosip.kernel.syncdata.exception.SyncDataServiceException; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import io.mosip.kernel.clientcrypto.constant.ClientType; import io.mosip.kernel.clientcrypto.dto.TpmCryptoRequestDto; import io.mosip.kernel.clientcrypto.dto.TpmCryptoResponseDto;