From db7bcd1d549ff89f5e7743ca49d38dfa5a04bb9d Mon Sep 17 00:00:00 2001 From: RM Date: Sat, 3 Oct 2026 02:47:02 +0300 Subject: [PATCH] first tests --- lombok.config | 1 + pom.xml | 89 ++++-- .../pledge/torgi/service/EmailService.java | 7 +- .../DownloadHeadlessControllerTest.java | 44 +++ .../controller/HealthControllerTest.java | 21 ++ .../storage/FileServiceImplTest.java | 194 +++++++++++++ ...DownloadHeadlessServiceAdditionalTest.java | 84 ++++++ .../DownloadHeadlessServiceCoverageTest.java | 262 ++++++++++++++++++ .../service/DownloadHeadlessServiceTest.java | 72 +++++ .../torgi/service/EmailServiceTest.java | 167 +++++++++++ .../com/pledge/torgi/service/LotTest.java | 91 ++++++ .../torgi/service/SendEmailServiceTest.java | 34 +++ .../pledge/torgi/utils/StartParamsTest.java | 39 +++ 13 files changed, 1075 insertions(+), 30 deletions(-) create mode 100644 lombok.config create mode 100644 src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java create mode 100644 src/test/java/com/pledge/torgi/controller/HealthControllerTest.java create mode 100644 src/test/java/com/pledge/torgi/controller/storage/FileServiceImplTest.java create mode 100644 src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceAdditionalTest.java create mode 100644 src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceCoverageTest.java create mode 100644 src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceTest.java create mode 100644 src/test/java/com/pledge/torgi/service/EmailServiceTest.java create mode 100644 src/test/java/com/pledge/torgi/service/LotTest.java create mode 100644 src/test/java/com/pledge/torgi/service/SendEmailServiceTest.java create mode 100644 src/test/java/com/pledge/torgi/utils/StartParamsTest.java diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..8f7e8aa --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +lombok.addLombokGeneratedAnnotation = true \ No newline at end of file diff --git a/pom.xml b/pom.xml index 57993b2..2d22f99 100644 --- a/pom.xml +++ b/pom.xml @@ -109,6 +109,67 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.0 + + "@{jacocoArgLine}" -Xshare:off -Dfile.encoding=UTF-8 + 1 + true + + + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + default-prepare-agent + + prepare-agent + + + jacocoArgLine + + C:/Temp/jacoco.exec + + + + default-report + test + + report + + + + C:/Temp/jacoco.exec + ${project.reporting.outputDirectory}/jacoco + + + + default-check + + check + + + + + BUNDLE + + + COMPLEXITY + COVEREDRATIO + 0.70 + + + + + + + + org.jsonschema2pojo jsonschema2pojo-maven-plugin @@ -129,32 +190,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/java/com/pledge/torgi/service/EmailService.java b/src/main/java/com/pledge/torgi/service/EmailService.java index 71c3e8e..12f62fa 100644 --- a/src/main/java/com/pledge/torgi/service/EmailService.java +++ b/src/main/java/com/pledge/torgi/service/EmailService.java @@ -26,8 +26,7 @@ public class EmailService { return; } List alreadyProcessed = emailsRepository.findTop10ByOrderByIdDesc(); - List emailData = new ReceiveEmailService("imap.gmail.com", 993, params.getFrom(), params.getToken(), params.getSpecialEmail(), log) - .downloadEmails(alreadyProcessed); + List emailData = createReceiveEmailService(params).downloadEmails(alreadyProcessed); int sendLetters = 0; log.info("Extracted letters = {}", emailData.size()); for (EmailData data : emailData) { @@ -41,6 +40,10 @@ public class EmailService { log.info("End email processing, send letters = {}", sendLetters); } + protected ReceiveEmailService createReceiveEmailService(StartParams params) { + return new ReceiveEmailService("imap.gmail.com", 993, params.getFrom(), params.getToken(), params.getSpecialEmail(), log); + } + private boolean alreadyProcessed(String emailId) { return emailsRepository.existsByMailId(emailId); } diff --git a/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java b/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java new file mode 100644 index 0000000..0a9b02b --- /dev/null +++ b/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java @@ -0,0 +1,44 @@ +package com.pledge.torgi.controller; + +import com.pledge.torgi.model.TorgiEvent; +import com.pledge.torgi.repositories.MissedDataRepository; +import com.pledge.torgi.repositories.TorgiEventRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class DownloadHeadlessControllerTest { + + @Mock + private TorgiEventRepository eventRepository; + + @Mock + private MissedDataRepository missedDataRepository; + + @Test + void constructor_shouldLoadExistingKeys() { + // given + TorgiEvent event = new TorgiEvent(); + event.setKey("test-key"); + Page page = new PageImpl<>(List.of(event)); + + when(eventRepository.findAllByOrderByCreatedAtDesc(any(PageRequest.class))) + .thenReturn(page); + + // when + new DownloadHeadlessController(eventRepository, missedDataRepository); + + // then + verify(eventRepository).findAllByOrderByCreatedAtDesc(any(PageRequest.class)); + } +} diff --git a/src/test/java/com/pledge/torgi/controller/HealthControllerTest.java b/src/test/java/com/pledge/torgi/controller/HealthControllerTest.java new file mode 100644 index 0000000..74ffb03 --- /dev/null +++ b/src/test/java/com/pledge/torgi/controller/HealthControllerTest.java @@ -0,0 +1,21 @@ +package com.pledge.torgi.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +class HealthControllerTest { + + private final HealthController controller = new HealthController(); + + @Test + void getHealth_shouldReturnOk() { + // when + ResponseEntity response = controller.getPerson(); + + // then + assertThat(response.getStatusCode().is2xxSuccessful()).isTrue(); + assertThat(response.getBody()).isEqualTo("OK"); + } +} diff --git a/src/test/java/com/pledge/torgi/controller/storage/FileServiceImplTest.java b/src/test/java/com/pledge/torgi/controller/storage/FileServiceImplTest.java new file mode 100644 index 0000000..bce2109 --- /dev/null +++ b/src/test/java/com/pledge/torgi/controller/storage/FileServiceImplTest.java @@ -0,0 +1,194 @@ +package com.pledge.torgi.controller.storage; + +import com.pledge.torgi.controller.DownloadHeadlessController; +import com.pledge.torgi.model.MissedData; +import com.pledge.torgi.repositories.MissedDataRepository; +import com.pledge.torgi.utils.StartParams; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class FileServiceImplTest { + + @Mock + private DownloadHeadlessController headlessController; + + @Mock + private StartParams params; + + @Mock + private MissedDataRepository missedDataRepository; + + @InjectMocks + private FileServiceImpl fileService; + + @Test + void extractCadastral_shouldExtractSingleCadastral() throws IOException { + // given + Workbook workbook = createWorkbookWithData("77:01:0001001:1234"); + + // when + List result = invokeExtractCadastral(workbook); + + // then + assertThat(result).containsExactly("77:01:0001001:1234"); + } + + @Test + void extractCadastral_shouldExtractMultipleCadastrals() throws IOException { + // given + Workbook workbook = createWorkbookWithData("77:01:0001001:1234", "77:01:0001001:5678"); + + // when + List result = invokeExtractCadastral(workbook); + + // then + assertThat(result).containsExactly("77:01:0001001:1234", "77:01:0001001:5678"); + } + + @Test + void extractCadastral_shouldReturnEmptyForEmptyCell() throws IOException { + // given + Workbook workbook = createWorkbookWithData(""); + + // when + List result = invokeExtractCadastral(workbook); + + // then + assertThat(result).isEmpty(); + } + + @Test + void extractCadastral_shouldReturnEmptyForWorkbookWithNoRows() throws IOException { + // given + Workbook workbook = new XSSFWorkbook(); + workbook.createSheet("Sheet1"); + + // when + List result = invokeExtractCadastral(workbook); + + // then + assertThat(result).isEmpty(); + } + + @Test + void processSync_shouldProcessFile() throws IOException { + // given + Workbook workbook = createWorkbookWithData("77:01:0001001:1234"); + when(missedDataRepository.findAll()).thenReturn(List.of()); + + // when + String result = fileService.processSync(workbook, "test@example.com"); + + // then + assertThat(result).isEqualTo("Обработано 1 кадастровых номеров"); + verify(headlessController).sendNewContent(any(), anyList(), anyString()); + } + + @Test + void processAsync_shouldProcessFile() throws IOException { + // given + MultipartFile file = createMultipartFileWithData("77:01:0001001:1234"); + + // when + String result = fileService.processAsync(file, "test@example.com"); + + // then + assertThat(result).isEqualTo("Взято в обработку 1 кадастровых номеров"); + } + + @Test + void saveCadastralToGetMissedData_shouldSaveNewCadastrals() { + // given + List cadastrals = List.of("77:01:0001001:1234", "77:01:0001001:5678"); + MissedData existing = new MissedData(); + existing.setCadastral("77:01:0001001:9999"); + when(missedDataRepository.findAll()).thenReturn(List.of(existing)); + + // when + invokeSaveCadastralToGetMissedData(cadastrals); + + // then + verify(missedDataRepository).saveAll(anyList()); + } + + @Test + void saveCadastralToGetMissedData_shouldNotSaveExistingCadastrals() { + // given + List cadastrals = List.of("77:01:0001001:1234"); + MissedData existing = new MissedData(); + existing.setCadastral("77:01:0001001:1234"); + when(missedDataRepository.findAll()).thenReturn(List.of(existing)); + + // when + invokeSaveCadastralToGetMissedData(cadastrals); + + // then + @SuppressWarnings("unchecked") + ArgumentCaptor> captor = ArgumentCaptor.forClass(Iterable.class); + verify(missedDataRepository).saveAll(captor.capture()); + assertThat(captor.getValue()).isEmpty(); + } + + // Helper methods + + private Workbook createWorkbookWithData(String... values) { + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("Sheet1"); + for (int i = 0; i < values.length; i++) { + Row row = sheet.createRow(i); + row.createCell(0).setCellValue(values[i]); + } + return workbook; + } + + private MultipartFile createMultipartFileWithData(String... values) throws IOException { + Workbook workbook = createWorkbookWithData(values); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + workbook.write(out); + return new MockMultipartFile("file", "test.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", new ByteArrayInputStream(out.toByteArray())); + } + + @SuppressWarnings("unchecked") + private List invokeExtractCadastral(Workbook workbook) { + try { + var method = FileServiceImpl.class.getDeclaredMethod("extractCadastral", Workbook.class); + method.setAccessible(true); + return (List) method.invoke(fileService, workbook); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("unchecked") + private void invokeSaveCadastralToGetMissedData(List cadastrals) { + try { + var method = FileServiceImpl.class.getDeclaredMethod("saveCadastralToGetMissedData", List.class); + method.setAccessible(true); + method.invoke(fileService, cadastrals); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceAdditionalTest.java b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceAdditionalTest.java new file mode 100644 index 0000000..21fe2b7 --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceAdditionalTest.java @@ -0,0 +1,84 @@ +package com.pledge.torgi.service; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class DownloadHeadlessServiceAdditionalTest { + + private final DownloadHeadlessService service = new DownloadHeadlessService(); + + @Test + void extractCadastral_shouldExtractMultipleCadastralsWithComma() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234,77:01:0001001:5678"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234", "77:01:0001001:5678"); + } + + @Test + void extractCadastral_shouldExtractConditionalNumber() { + // given + String rawValue = "Условный номер земельного участка: 77:01:0001001:1234"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234"); + } + + @Test + void extractCadastral_shouldHandleMixedTypes() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234;VIN: X9FKXXEEBMD123456"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234", "X9FKXXEEBMD123456"); + } + + @Test + void extractCadastral_shouldHandleEmptyParts() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234;;VIN: X9FKXXEEBMD123456"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234", "X9FKXXEEBMD123456"); + } + + @Test + void extractCadastral_shouldHandleSpaces() { + // given + String rawValue = " Кадастровый номер : 77:01:0001001:1234 "; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234"); + } + + @Test + void extractCadastral_shouldExtractSingleCadastralWithType() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234"); + } +} diff --git a/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceCoverageTest.java b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceCoverageTest.java new file mode 100644 index 0000000..afba654 --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceCoverageTest.java @@ -0,0 +1,262 @@ +package com.pledge.torgi.service; + +import com.pledge.torgi.model.TorgiEvent; +import com.pledge.torgi.repositories.TorgiEventRepository; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import java.util.ArrayList; + +import java.io.ByteArrayOutputStream; +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DownloadHeadlessServiceCoverageTest { + + @Mock + private TorgiEventRepository eventRepository; + + private final DownloadHeadlessService service = new DownloadHeadlessService(); + + @Test + void extractData_shouldReturnEmptyForNoCadastrals() { + // given + List cadastrals = List.of(); + + // when + List result = invokeExtractData(cadastrals); + + // then + assertThat(result).isEmpty(); + } + + @Test + void extractData_shouldReturnLotsForCadastral() { + // given + List cadastrals = List.of("77:01:0001001:1234"); + TorgiEvent event = new TorgiEvent(); + event.setKey("test-key"); + event.setStatus("PUBLISHED"); + event.setBidStart("2024-01-01"); + event.setBidEnd("2024-01-31"); + event.setTradesDate("2024-02-01"); + event.setStartPrice("1000000"); + event.setStep("10000"); + event.setInitMoney("50000"); + event.setFinalPrice("1200000"); + event.setNotice("Notice123"); + event.setLotNumber(1); + event.setCadastral("77:01:0001001:1234"); + event.setType("Earth"); + event.setFullInfo("Full info"); + when(eventRepository.findAllByFullInfoLikeOrderByCreatedAtDesc(anyString())).thenReturn(List.of(event)); + + // when + List result = invokeExtractData(cadastrals); + + // then + assertThat(result).hasSize(1); + assertThat(result.get(0).getStatus()).isEqualTo("PUBLISHED"); + assertThat(result.get(0).getNotice()).isEqualTo("Notice123"); + } + + @Test + void extractData_shouldHandleMultipleCadastrals() { + // given + List cadastrals = List.of("77:01:0001001:1234", "77:01:0001001:5678"); + TorgiEvent event1 = new TorgiEvent(); + event1.setKey("test-key-1"); + event1.setStatus("PUBLISHED"); + event1.setCadastral("77:01:0001001:1234"); + TorgiEvent event2 = new TorgiEvent(); + event2.setKey("test-key-2"); + event2.setStatus("CANCELED"); + event2.setCadastral("77:01:0001001:5678"); + when(eventRepository.findAllByFullInfoLikeOrderByCreatedAtDesc(anyString())).thenReturn(List.of(event1, event2)); + + // when + List result = invokeExtractData(cadastrals); + + // then + assertThat(result).hasSize(2); + } + + @Test + void extractData_shouldHandleRepositoryException() { + // given + List cadastrals = List.of("77:01:0001001:1234"); + when(eventRepository.findAllByFullInfoLikeOrderByCreatedAtDesc(anyString())) + .thenThrow(new RuntimeException("Database error")); + + // when + List result = invokeExtractData(cadastrals); + + // then + assertThat(result).isEmpty(); + } + + @Test + void getFileToSave_shouldReturnFile() { + // given + LocalDate now = LocalDate.now(); + + // when + java.io.File result = invokeGetFileToSave(now); + + // then + assertThat(result).isNotNull(); + assertThat(result.getName()).isEqualTo(now + ".xlsx"); + } + + @Test + void setRowHead_shouldCreateHeader() { + // given + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet("Sheet1"); + + // when + invokeSetRowHead(sheet); + + // then + Row headerRow = sheet.getRow(0); + assertThat(headerRow).isNotNull(); + assertThat(headerRow.getCell(0).getStringCellValue()).isEqualTo("Статус торгов"); + assertThat(headerRow.getCell(1).getStringCellValue()).isEqualTo("Дата начала подачи заявок"); + assertThat(headerRow.getCell(13).getStringCellValue()).isEqualTo("Время получения события"); + } + + @Test + void createRow_shouldCreateRow() { + // given + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet("Sheet1"); + Lot lot = new Lot(); + lot.setStatus("PUBLISHED"); + lot.setBidStart("2024-01-01"); + lot.setBidEnd("2024-01-31"); + lot.setTradesDate("2024-02-01"); + lot.setStartPrice("1000000"); + lot.setStep("10000"); + lot.setInitMoney("50000"); + lot.setFinalPrice("1200000"); + lot.setNotice("Notice123"); + lot.setLotNumber(1); + lot.setCadastral("77:01:0001001:1234"); + lot.setType("Earth"); + lot.setFullInfo("Full info"); + + // when + int result = invokeCreateRow(sheet, 0, lot); + + // then + assertThat(result).isEqualTo(1); + Row row = sheet.getRow(0); + assertThat(row).isNotNull(); + assertThat(row.getCell(0).getStringCellValue()).isEqualTo("PUBLISHED"); + assertThat(row.getCell(8).getStringCellValue()).isEqualTo("Notice123"); + } + + @Test + void createRow_shouldHandleNullValues() { + // given + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet("Sheet1"); + Lot lot = new Lot(); + + // when + int result = invokeCreateRow(sheet, 0, lot); + + // then + assertThat(result).isEqualTo(1); + Row row = sheet.getRow(0); + assertThat(row).isNotNull(); + assertThat(row.getCell(0).getStringCellValue()).isEmpty(); + } + + @Test + void setRowBodyNew_shouldCreateRows() { + // given + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet("Sheet1"); + Lot lot1 = new Lot(); + lot1.setStatus("PUBLISHED"); + lot1.setNotice("Notice1"); + Lot lot2 = new Lot(); + lot2.setStatus("CANCELED"); + lot2.setNotice("Notice2"); + List lots = List.of(lot1, lot2); + + // when + int result = invokeSetRowBodyNew(sheet, 0, lots); + + // then + assertThat(result).isEqualTo(2); + assertThat(sheet.getRow(0) != null).isTrue(); + assertThat(sheet.getRow(1) != null).isTrue(); + } + + // Helper methods + + @SuppressWarnings("unchecked") + private List invokeExtractData(List cadastrals) { + try { + var method = DownloadHeadlessService.class.getDeclaredMethod("extractData", TorgiEventRepository.class, List.class); + method.setAccessible(true); + return (List) method.invoke(service, eventRepository, cadastrals); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private java.io.File invokeGetFileToSave(LocalDate now) { + try { + var method = DownloadHeadlessService.class.getDeclaredMethod("getFileToSave", LocalDate.class); + method.setAccessible(true); + return (java.io.File) method.invoke(service, now); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void invokeSetRowHead(XSSFSheet sheet) { + try { + var method = DownloadHeadlessService.class.getDeclaredMethod("setRowHead", XSSFSheet.class); + method.setAccessible(true); + method.invoke(service, sheet); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private int invokeCreateRow(XSSFSheet sheet, int rowCount, Lot lot) { + try { + var method = DownloadHeadlessService.class.getDeclaredMethod("createRow", XSSFSheet.class, int.class, Lot.class); + method.setAccessible(true); + return (int) method.invoke(service, sheet, rowCount, lot); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private int invokeSetRowBodyNew(XSSFSheet sheet, int currentRow, List lots) { + try { + var method = DownloadHeadlessService.class.getDeclaredMethod("setRowBodyNew", XSSFSheet.class, int.class, java.util.Collection.class); + method.setAccessible(true); + return (int) method.invoke(service, sheet, currentRow, lots); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceTest.java b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceTest.java new file mode 100644 index 0000000..0700ebd --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/DownloadHeadlessServiceTest.java @@ -0,0 +1,72 @@ +package com.pledge.torgi.service; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class DownloadHeadlessServiceTest { + + private final DownloadHeadlessService service = new DownloadHeadlessService(); + + @Test + void extractCadastral_shouldExtractSingleCadastral() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234"); + } + + @Test + void extractCadastral_shouldExtractMultipleCadastrals() { + // given + String rawValue = "Кадастровый номер: 77:01:0001001:1234|77:01:0001001:5678"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("77:01:0001001:1234", "77:01:0001001:5678"); + } + + @Test + void extractCadastral_shouldExtractVIN() { + // given + String rawValue = "VIN: X9FKXXEEBMD123456"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).containsExactly("X9FKXXEEBMD123456"); + } + + @Test + void extractCadastral_shouldReturnEmptyForUnknownType() { + // given + String rawValue = "Неизвестный тип: значение"; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).isEmpty(); + } + + @Test + void extractCadastral_shouldReturnEmptyForEmptyInput() { + // given + String rawValue = ""; + + // when + List result = service.extractCadastral(rawValue); + + // then + assertThat(result).isEmpty(); + } +} diff --git a/src/test/java/com/pledge/torgi/service/EmailServiceTest.java b/src/test/java/com/pledge/torgi/service/EmailServiceTest.java new file mode 100644 index 0000000..ae1b247 --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/EmailServiceTest.java @@ -0,0 +1,167 @@ +package com.pledge.torgi.service; + +import com.pledge.torgi.controller.storage.FileService; +import com.pledge.torgi.model.Emails; +import com.pledge.torgi.repositories.EmailsRepository; +import com.pledge.torgi.utils.StartParams; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +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 java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class EmailServiceTest { + + @Mock + private FileService fileService; + + @Mock + private EmailsRepository emailsRepository; + + @Spy + @InjectMocks + private EmailService emailService; + + @Test + void processEmails_shouldSkipWhenDisabled() { + // given + StartParams params = new StartParams(); + params.setEnableEmailScan(false); + + // when + emailService.processEmails(params); + + // then + verifyNoInteractions(emailsRepository); + } + + @Test + void processEmails_shouldProcessWhenEnabled() { + // given + StartParams params = new StartParams(); + params.setEnableEmailScan(true); + params.setFrom("test@gmail.com"); + params.setToken("token"); + params.setSpecialEmail("special@gmail.com"); + + when(emailsRepository.findTop10ByOrderByIdDesc()).thenReturn(List.of()); + + ReceiveEmailService mockReceiveEmailService = mock(ReceiveEmailService.class); + when(mockReceiveEmailService.downloadEmails(any())).thenReturn(List.of()); + doReturn(mockReceiveEmailService).when(emailService).createReceiveEmailService(any()); + + // when + emailService.processEmails(params); + + // then + verify(emailsRepository).findTop10ByOrderByIdDesc(); + verify(mockReceiveEmailService).downloadEmails(any()); + } + + @Test + void processEmails_shouldProcessNewEmails() { + // given + StartParams params = new StartParams(); + params.setEnableEmailScan(true); + params.setFrom("test@gmail.com"); + params.setToken("token"); + params.setSpecialEmail("special@gmail.com"); + + Emails processedEmail = new Emails(); + processedEmail.setMailId("existing-id"); + when(emailsRepository.findTop10ByOrderByIdDesc()).thenReturn(List.of(processedEmail)); + + EmailData newEmailData = new EmailData(); + newEmailData.setEmailId("new-email-id"); + newEmailData.setEmails("test@example.com"); + newEmailData.setFile(new XSSFWorkbook()); + + ReceiveEmailService mockReceiveEmailService = mock(ReceiveEmailService.class); + when(mockReceiveEmailService.downloadEmails(any())).thenReturn(List.of(newEmailData)); + doReturn(mockReceiveEmailService).when(emailService).createReceiveEmailService(any()); + + when(emailsRepository.existsByMailId("new-email-id")).thenReturn(false); + + // when + emailService.processEmails(params); + + // then + verify(emailsRepository).existsByMailId("new-email-id"); + verify(fileService).processSync(any(), anyString()); + verify(emailsRepository).save(any(Emails.class)); + } + + @Test + void processEmails_shouldSkipAlreadyProcessedEmails() { + // given + StartParams params = new StartParams(); + params.setEnableEmailScan(true); + params.setFrom("test@gmail.com"); + params.setToken("token"); + params.setSpecialEmail("special@gmail.com"); + + Emails processedEmail = new Emails(); + processedEmail.setMailId("existing-id"); + when(emailsRepository.findTop10ByOrderByIdDesc()).thenReturn(List.of(processedEmail)); + + EmailData existingEmailData = new EmailData(); + existingEmailData.setEmailId("existing-id"); + existingEmailData.setEmails("test@example.com"); + existingEmailData.setFile(new XSSFWorkbook()); + + ReceiveEmailService mockReceiveEmailService = mock(ReceiveEmailService.class); + when(mockReceiveEmailService.downloadEmails(any())).thenReturn(List.of(existingEmailData)); + doReturn(mockReceiveEmailService).when(emailService).createReceiveEmailService(any()); + + when(emailsRepository.existsByMailId("existing-id")).thenReturn(true); + + // when + emailService.processEmails(params); + + // then + verify(emailsRepository).existsByMailId("existing-id"); + verifyNoInteractions(fileService); + verify(emailsRepository, never()).save(any(Emails.class)); + } + + @Test + void processEmails_shouldSaveProcessedEmail() { + // given + StartParams params = new StartParams(); + params.setEnableEmailScan(true); + params.setFrom("test@gmail.com"); + params.setToken("token"); + params.setSpecialEmail("special@gmail.com"); + + when(emailsRepository.findTop10ByOrderByIdDesc()).thenReturn(List.of()); + + EmailData emailData = new EmailData(); + emailData.setEmailId("new-id"); + emailData.setEmails("test@example.com"); + emailData.setFile(new XSSFWorkbook()); + + ReceiveEmailService mockReceiveEmailService = mock(ReceiveEmailService.class); + when(mockReceiveEmailService.downloadEmails(any())).thenReturn(List.of(emailData)); + doReturn(mockReceiveEmailService).when(emailService).createReceiveEmailService(any()); + + when(emailsRepository.existsByMailId("new-id")).thenReturn(false); + + // when + emailService.processEmails(params); + + // then + verify(emailsRepository).save(argThat(email -> + email.getMailId().equals("new-id") && + email.getReplyTo().equals("test@example.com") + )); + } +} diff --git a/src/test/java/com/pledge/torgi/service/LotTest.java b/src/test/java/com/pledge/torgi/service/LotTest.java new file mode 100644 index 0000000..4b27637 --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/LotTest.java @@ -0,0 +1,91 @@ +package com.pledge.torgi.service; + +import com.pledge.torgi.model.TorgiEvent; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class LotTest { + + @Test + void defaultConstructor_shouldCreateInstance() { + // when + Lot lot = new Lot(); + + // then + assertThat(lot).isNotNull(); + } + + @Test + void constructorFromTorgiEvent_shouldCopyFields() { + // given + TorgiEvent event = new TorgiEvent(); + event.setStatus("PUBLISHED"); + event.setBidStart("2024-01-01"); + event.setBidEnd("2024-01-31"); + event.setTradesDate("2024-02-01"); + event.setStartPrice("1000000"); + event.setStep("10000"); + event.setInitMoney("50000"); + event.setFinalPrice("1200000"); + event.setNotice("Notice123"); + event.setLotNumber(1); + event.setCadastral("77:01:0001001:1234"); + event.setType("Earth"); + event.setFullInfo("Full info"); + + // when + Lot lot = new Lot(event); + + // then + assertThat(lot.getStatus()).isEqualTo("PUBLISHED"); + assertThat(lot.getBidStart()).isEqualTo("2024-01-01"); + assertThat(lot.getBidEnd()).isEqualTo("2024-01-31"); + assertThat(lot.getTradesDate()).isEqualTo("2024-02-01"); + assertThat(lot.getStartPrice()).isEqualTo("1000000"); + assertThat(lot.getStep()).isEqualTo("10000"); + assertThat(lot.getInitMoney()).isEqualTo("50000"); + assertThat(lot.getFinalPrice()).isEqualTo("1200000"); + assertThat(lot.getNotice()).isEqualTo("Notice123"); + assertThat(lot.getLotNumber()).isEqualTo(1); + assertThat(lot.getCadastral()).isEqualTo("77:01:0001001:1234"); + assertThat(lot.getType()).isEqualTo("Earth"); + assertThat(lot.getFullInfo()).isEqualTo("Full info"); + } + + @Test + void settersAndGetters_shouldWork() { + // given + Lot lot = new Lot(); + + // when + lot.setStatus("PUBLISHED"); + lot.setBidStart("2024-01-01"); + lot.setBidEnd("2024-01-31"); + lot.setTradesDate("2024-02-01"); + lot.setStartPrice("1000000"); + lot.setStep("10000"); + lot.setInitMoney("50000"); + lot.setFinalPrice("1200000"); + lot.setNotice("Notice123"); + lot.setLotNumber(1); + lot.setCadastral("77:01:0001001:1234"); + lot.setType("Earth"); + lot.setFullInfo("Full info"); + + // then + assertThat(lot.getStatus()).isEqualTo("PUBLISHED"); + assertThat(lot.getBidStart()).isEqualTo("2024-01-01"); + assertThat(lot.getBidEnd()).isEqualTo("2024-01-31"); + assertThat(lot.getTradesDate()).isEqualTo("2024-02-01"); + assertThat(lot.getStartPrice()).isEqualTo("1000000"); + assertThat(lot.getStep()).isEqualTo("10000"); + assertThat(lot.getInitMoney()).isEqualTo("50000"); + assertThat(lot.getFinalPrice()).isEqualTo("1200000"); + assertThat(lot.getNotice()).isEqualTo("Notice123"); + assertThat(lot.getLotNumber()).isEqualTo(1); + assertThat(lot.getCadastral()).isEqualTo("77:01:0001001:1234"); + assertThat(lot.getType()).isEqualTo("Earth"); + assertThat(lot.getFullInfo()).isEqualTo("Full info"); + } +} diff --git a/src/test/java/com/pledge/torgi/service/SendEmailServiceTest.java b/src/test/java/com/pledge/torgi/service/SendEmailServiceTest.java new file mode 100644 index 0000000..902ef15 --- /dev/null +++ b/src/test/java/com/pledge/torgi/service/SendEmailServiceTest.java @@ -0,0 +1,34 @@ +package com.pledge.torgi.service; + +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +class SendEmailServiceTest { + + @Test + void constructor_shouldCreateInstance() { + // when + SendEmailService service = new SendEmailService("smtp.gmail.com", 587, "user", "pass"); + + // then + assertThat(service).isNotNull(); + } + + @Test + void sendMail_shouldThrowExceptionForInvalidFile() { + // given + SendEmailService service = new SendEmailService("smtp.gmail.com", 587, "user", "pass"); + File nonExistentFile = new File("non-existent.zip"); + + // when & then + try { + service.sendMail("from@test.com", "to@test.com", "Subject", "Body", nonExistentFile); + } catch (Exception e) { + // Expected - file doesn't exist + assertThat(e).isNotNull(); + } + } +} diff --git a/src/test/java/com/pledge/torgi/utils/StartParamsTest.java b/src/test/java/com/pledge/torgi/utils/StartParamsTest.java new file mode 100644 index 0000000..f7ab20a --- /dev/null +++ b/src/test/java/com/pledge/torgi/utils/StartParamsTest.java @@ -0,0 +1,39 @@ +package com.pledge.torgi.utils; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class StartParamsTest { + + @Test + void defaultConstructor_shouldCreateInstance() { + // when + StartParams params = new StartParams(); + + // then + assertThat(params).isNotNull(); + } + + @Test + void settersAndGetters_shouldWork() { + // given + StartParams params = new StartParams(); + + // when + params.setFrom("test@gmail.com"); + params.setToken("token"); + params.setTo("to@gmail.com"); + params.setDays("1"); + params.setSpecialEmail("special@gmail.com"); + params.setEnableEmailScan(true); + + // then + assertThat(params.getFrom()).isEqualTo("test@gmail.com"); + assertThat(params.getToken()).isEqualTo("token"); + assertThat(params.getTo()).isEqualTo("to@gmail.com"); + assertThat(params.getDays()).isEqualTo("1"); + assertThat(params.getSpecialEmail()).isEqualTo("special@gmail.com"); + assertThat(params.getEnableEmailScan()).isTrue(); + } +}