From ffaa2fb2a0a5d3057d8b8849781eec7bc460e44f Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Tue, 21 Jul 2026 09:01:45 +0800 Subject: [PATCH] test --- .../CcdiCreditInfoServiceImplTest.java | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiCreditInfoServiceImplTest.java b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiCreditInfoServiceImplTest.java index e5b52326..7d1c85c0 100644 --- a/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiCreditInfoServiceImplTest.java +++ b/ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiCreditInfoServiceImplTest.java @@ -19,6 +19,7 @@ import com.ruoyi.lsfx.domain.response.CreditParseResponse; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; +import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -35,16 +36,25 @@ import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class CcdiCreditInfoServiceImplTest { private static final CallerContext CALLER = CallerContext.of(7L, "tester"); + private static final CreditHtmlStorageService.StoredCreditHtml STORED_HTML = + new CreditHtmlStorageService.StoredCreditHtml( + "/profile/credit-html/2026/05/12/a_1.html", + "http://127.0.0.1:62318/profile/credit-html/2026/05/12/a_1.html"); @InjectMocks private CcdiCreditInfoServiceImpl service; @@ -87,8 +97,12 @@ class CcdiCreditInfoServiceImplTest { assertEquals(1, result.getSuccessCount()); assertEquals(0, result.getFailureCount()); - verify(creditParseClient).parse(CALLER, "http://127.0.0.1:62318/profile/credit-html/2026/05/12/family_1.html"); - verify(debtsInfoMapper).deleteByPersonId("330101199202020022"); + InOrder processingOrder = inOrder(creditParseClient, creditHtmlStorageService, debtsInfoMapper); + processingOrder.verify(creditParseClient) + .parse(CALLER, "http://127.0.0.1:62318/profile/credit-html/2026/05/12/family_1.html"); + processingOrder.verify(creditHtmlStorageService) + .delete(any(CreditHtmlStorageService.StoredCreditHtml.class)); + processingOrder.verify(debtsInfoMapper).deleteByPersonId("330101199202020022"); verify(negativeInfoMapper).deleteByPersonId("330101199202020022"); } @@ -109,6 +123,7 @@ class CcdiCreditInfoServiceImplTest { assertEquals(0, result.getSuccessCount()); assertEquals("上传征信日期早于当前已维护最新记录", result.getFailures().get(0).getReason()); + verify(creditHtmlStorageService).delete(STORED_HTML); } @Test @@ -127,6 +142,7 @@ class CcdiCreditInfoServiceImplTest { assertEquals(0, result.getSuccessCount()); assertEquals("征信解析平台状态码异常: 99999", result.getFailures().get(0).getReason()); + verify(creditHtmlStorageService).delete(STORED_HTML); } @Test @@ -147,11 +163,77 @@ class CcdiCreditInfoServiceImplTest { assertEquals(0, result.getSuccessCount()); assertEquals("结果解析失败", result.getFailures().get(0).getReason()); + verify(creditHtmlStorageService).delete(STORED_HTML); + } + + @Test + void uploadHtmlFiles_shouldDeleteBeforeDatabaseFailure() throws Exception { + MockMultipartFile file = htmlFile("a.html"); + when(creditHtmlStorageService.save(any())).thenReturn(STORED_HTML); + when(creditParseClient.parse(any(CallerContext.class), anyString())) + .thenReturn(successResponse("330101199001010011", "张三", "2026-03-03")); + when(assembler.buildDebts(anyString(), anyString(), any(LocalDate.class), any(CreditParsePayload.class))) + .thenReturn(List.of(buildDebt("330101199001010011"))); + when(assembler.buildNegative(anyString(), anyString(), any(LocalDate.class), any(CreditParsePayload.class))) + .thenReturn(buildNegative("330101199001010011")); + doThrow(new RuntimeException("入库失败")) + .when(debtsInfoMapper).deleteByPersonId("330101199001010011"); + + CreditInfoUploadResultVO result = service.upload(List.of(file), CALLER); + + assertEquals(0, result.getSuccessCount()); + assertEquals("入库失败", result.getFailures().get(0).getReason()); + InOrder processingOrder = inOrder(creditHtmlStorageService, debtsInfoMapper); + processingOrder.verify(creditHtmlStorageService).delete(STORED_HTML); + processingOrder.verify(debtsInfoMapper).deleteByPersonId("330101199001010011"); + } + + @Test + void uploadHtmlFiles_shouldFailBeforeValidationWhenDeleteFails() throws Exception { + MockMultipartFile file = htmlFile("a.html"); + when(creditHtmlStorageService.save(any())).thenReturn(STORED_HTML); + when(creditParseClient.parse(any(CallerContext.class), anyString())) + .thenReturn(successResponse("330101199001010011", "张三", "2026-03-03")); + doThrow(new java.io.IOException("本地文件删除失败")) + .when(creditHtmlStorageService).delete(STORED_HTML); + + CreditInfoUploadResultVO result = service.upload(List.of(file), CALLER); + + assertEquals(0, result.getSuccessCount()); + assertEquals("本地文件删除失败", result.getFailures().get(0).getReason()); + verifyNoInteractions(assembler, debtsInfoMapper, negativeInfoMapper, queryMapper); + } + + @Test + void uploadHtmlFiles_shouldPreserveParseErrorAndContinueWhenDeleteAlsoFails() throws Exception { + MockMultipartFile failedFile = htmlFile("failed.html"); + MockMultipartFile successFile = htmlFile("success.html"); + CreditHtmlStorageService.StoredCreditHtml failedStoredHtml = storedHtml("failed_1.html"); + CreditHtmlStorageService.StoredCreditHtml successStoredHtml = storedHtml("success_1.html"); + when(creditHtmlStorageService.save(any())).thenReturn(failedStoredHtml, successStoredHtml); + when(creditParseClient.parse(any(CallerContext.class), anyString())) + .thenThrow(new RuntimeException("解析接口异常")) + .thenReturn(successResponse("330101199001010011", "张三", "2026-03-03")); + doThrow(new java.io.IOException("本地文件删除失败")) + .doNothing() + .when(creditHtmlStorageService).delete(any(CreditHtmlStorageService.StoredCreditHtml.class)); + when(assembler.buildDebts(anyString(), anyString(), any(LocalDate.class), any(CreditParsePayload.class))) + .thenReturn(List.of()); + when(assembler.buildNegative(anyString(), anyString(), any(LocalDate.class), any(CreditParsePayload.class))) + .thenReturn(null); + + CreditInfoUploadResultVO result = service.upload(List.of(failedFile, successFile), CALLER); + + assertEquals(1, result.getSuccessCount()); + assertEquals(1, result.getFailureCount()); + assertEquals("解析接口异常", result.getFailures().get(0).getReason()); + verify(creditHtmlStorageService).delete(failedStoredHtml); + verify(creditHtmlStorageService).delete(successStoredHtml); } @Test - void creditHtmlStorage_shouldStoreHtmlUnderProfileAndBuildRemotePath(@TempDir Path profileDir) throws Exception { + void creditHtmlStorage_shouldStoreAndDeleteHtmlWithinProfile(@TempDir Path profileDir) throws Exception { String oldProfile = RuoYiConfig.getProfile(); new RuoYiConfig().setProfile(profileDir.toString()); try { @@ -167,11 +249,42 @@ class CcdiCreditInfoServiceImplTest { assertEquals("http://127.0.0.1:62318" + storedHtml.profilePath(), storedHtml.remotePath()); Path savedFile = profileDir.resolve(storedHtml.profilePath().substring("/profile/".length())); assertTrue(Files.exists(savedFile)); + storageService.delete(storedHtml); + assertFalse(Files.exists(savedFile)); + storageService.delete(storedHtml); } finally { new RuoYiConfig().setProfile(oldProfile); } } + @Test + void creditHtmlStorage_shouldRejectPathOutsideCreditHtmlDirectory(@TempDir Path profileDir) throws Exception { + String oldProfile = RuoYiConfig.getProfile(); + new RuoYiConfig().setProfile(profileDir.toString()); + try { + CreditHtmlStorageService storageService = new CreditHtmlStorageService(); + Path outsideFile = Files.writeString(profileDir.resolve("outside.html"), "outside"); + CreditHtmlStorageService.StoredCreditHtml storedHtml = new CreditHtmlStorageService.StoredCreditHtml( + "/profile/credit-html/../outside.html", "http://127.0.0.1/profile/credit-html/../outside.html"); + + assertThrows(IllegalArgumentException.class, () -> storageService.delete(storedHtml)); + assertTrue(Files.exists(outsideFile)); + } finally { + new RuoYiConfig().setProfile(oldProfile); + } + } + + private MockMultipartFile htmlFile(String fileName) { + return new MockMultipartFile( + "files", fileName, "text/html", "ok".getBytes(StandardCharsets.UTF_8)); + } + + private CreditHtmlStorageService.StoredCreditHtml storedHtml(String fileName) { + return new CreditHtmlStorageService.StoredCreditHtml( + "/profile/credit-html/2026/05/12/" + fileName, + "http://127.0.0.1:62318/profile/credit-html/2026/05/12/" + fileName); + } + private CreditParseInvokeResponse successResponse(String personId, String personName, String reportTime) { CreditParsePayload payload = new CreditParsePayload(); Map header = new HashMap<>();