This commit is contained in:
wkc
2026-07-21 09:01:45 +08:00
parent dc8055ce7a
commit ffaa2fb2a0

View File

@@ -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", "<html>ok</html>".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<String, Object> header = new HashMap<>();