From 1177c179e6cb984aeb9ca185bde661894060d536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Wed, 16 Sep 2026 19:26:35 +0800 Subject: [PATCH] =?UTF-8?q?:white=5Fcheck=5Fmark:=20=E6=96=B0=E5=A2=9EBFI?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=B1=82=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E5=AE=A2=E6=88=B7/=E5=BA=94=E4=BB=98/?= =?UTF-8?q?=E5=BA=94=E6=94=B6/=E7=A5=A8=E5=8A=A1/=E8=B5=84=E9=87=91?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bfi/service/BfiServiceImplTest.java | 592 ++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100644 blade-third-party-api/blade-bfi-api/src/test/java/org/springblade/thirdparty/bfi/service/BfiServiceImplTest.java diff --git a/blade-third-party-api/blade-bfi-api/src/test/java/org/springblade/thirdparty/bfi/service/BfiServiceImplTest.java b/blade-third-party-api/blade-bfi-api/src/test/java/org/springblade/thirdparty/bfi/service/BfiServiceImplTest.java new file mode 100644 index 00000000..4591ccb8 --- /dev/null +++ b/blade-third-party-api/blade-bfi-api/src/test/java/org/springblade/thirdparty/bfi/service/BfiServiceImplTest.java @@ -0,0 +1,592 @@ +/* + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is + * not liable for any claims arising from secondary or illegal development. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.thirdparty.bfi.service; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import feign.Request; +import feign.Response; +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 org.springblade.core.redis.cache.BladeRedis; +import org.springblade.thirdparty.bfi.config.BfiProperties; +import org.springblade.thirdparty.bfi.exception.BfiException; +import org.springblade.thirdparty.bfi.feign.IBfiClient; +import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillSaveDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillSaveEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiArBillQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiArBillSaveDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiArBillSaveEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiClaimAnnounceQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiClaimPushDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiClaimPushEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerSaveDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerGroupEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplyOpenApiQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplyQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplySaveEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignBodyDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignItemDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceAssignRefDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceSaveDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiReceivedInvoiceSaveEntryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiRecBillQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiTokenDTO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiApBillVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiArBillVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiClaimAnnounceVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoiceApplyVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiOpenApiResultVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiReceivedInvoiceVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiRecBillVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiResultVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiTokenVO; +import org.springframework.data.redis.core.ValueOperations; + +import org.springblade.thirdparty.bfi.service.impl.BfiServiceImpl; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +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.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +/** + * 业财融合(BFI)服务实现单元测试 + * + * @author Chill + */ +@ExtendWith(MockitoExtension.class) +class BfiServiceImplTest { + + @Mock + private BfiProperties properties; + + @Mock + private IBfiClient client; + + @Mock + private BladeRedis bladeRedis; + + @Mock + private ValueOperations valueOperations; + + @InjectMocks + private BfiServiceImpl service; + + @BeforeEach + void setUp() { + lenient().when(properties.getClientId()).thenReturn("test-client"); + lenient().when(properties.getClientSecret()).thenReturn("test-secret"); + lenient().when(properties.getUsername()).thenReturn("test-user"); + lenient().when(properties.getAccountId()).thenReturn("test-account"); + lenient().when(properties.getLanguage()).thenReturn("zh_CN"); + lenient().when(bladeRedis.getValueOps()).thenReturn(valueOperations); + } + + /** + * 构建成功响应 + */ + private BfiResultVO success(T data) { + BfiResultVO result = new BfiResultVO<>(); + result.setStatus(true); + result.setErrorCode("0"); + result.setData(data); + return result; + } + + /** + * 构建保存结果 + */ + private BfiBillSaveResultVO saveResult(int successCount) { + BfiBillSaveResultVO result = new BfiBillSaveResultVO(); + result.setSuccessCount(String.valueOf(successCount)); + result.setFailCount("0"); + return result; + } + + /** + * 构建令牌数据 + */ + private BfiTokenVO tokenVO() { + BfiTokenVO tokenVO = new BfiTokenVO(); + tokenVO.setAccessToken("token-1"); + tokenVO.setExpiresIn(600_000L); + return tokenVO; + } + + /** + * 模拟缓存未命中并通过 getToken 获取令牌 + */ + private void mockAccessToken() { + when(bladeRedis.get("blade:third:bfi:token")).thenReturn(null); + when(client.getToken(any(BfiTokenDTO.class))).thenReturn(success(tokenVO())); + } + + @Test + void getTokenShouldCacheAndReturnToken() { + when(client.getToken(any(BfiTokenDTO.class))).thenReturn(success(tokenVO())); + BfiTokenVO tokenVO = service.getToken(); + assertEquals("token-1", tokenVO.getAccessToken()); + ArgumentCaptor captor = ArgumentCaptor.forClass(BfiTokenDTO.class); + verify(client).getToken(captor.capture()); + assertEquals("test-client", captor.getValue().getClientId()); + assertNotNull(captor.getValue().getNonce()); + assertNotNull(captor.getValue().getTimestamp()); + verify(valueOperations).setIfAbsent(eq("blade:third:bfi:token"), eq("token-1"), any()); + } + + @Test + void getTokenShouldThrowWhenDataEmpty() { + when(client.getToken(any(BfiTokenDTO.class))).thenReturn(success(new BfiTokenVO())); + assertThrows(BfiException.class, () -> service.getToken()); + } + + @Test + void getAccessTokenShouldReturnCachedValue() { + when(bladeRedis.get("blade:third:bfi:token")).thenReturn("cached-token"); + assertEquals("cached-token", service.getAccessToken()); + verifyNoInteractions(client); + } + + @Test + void getAccessTokenShouldFetchWhenCacheMiss() { + mockAccessToken(); + assertEquals("token-1", service.getAccessToken()); + } + + @Test + void queryCustomerShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.customerQuery(eq("token-1"), eq(1), eq(10), any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(success(page)); + BfiCustomerQueryDTO param = new BfiCustomerQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + assertEquals(page, service.queryCustomer(param)); + } + + @Test + void queryCustomerShouldThrowWhenPageEmpty() { + assertThrows(BfiException.class, () -> service.queryCustomer(new BfiCustomerQueryDTO())); + } + + @Test + void saveCustomerShouldValidateRequiredFields() { + BfiCustomerSaveDTO noName = new BfiCustomerSaveDTO(); + assertThrows(BfiException.class, () -> service.saveCustomer(noName)); + + BfiCustomerSaveDTO noCreditCode = new BfiCustomerSaveDTO(); + noCreditCode.setName("客户A"); + noCreditCode.setEntryGroupstandard(List.of(new BfiCustomerGroupEntryDTO())); + assertThrows(BfiException.class, () -> service.saveCustomer(noCreditCode)); + + BfiCustomerSaveDTO noGroup = new BfiCustomerSaveDTO(); + noGroup.setName("客户A"); + noGroup.setSocietycreditcode("91450000MA5Q1G1M59"); + assertThrows(BfiException.class, () -> service.saveCustomer(noGroup)); + verifyNoInteractions(client); + } + + @Test + void saveCustomerShouldWrapData() { + mockAccessToken(); + when(client.customerSave(anyString(), any())).thenReturn(success(saveResult(1))); + BfiCustomerSaveDTO param = new BfiCustomerSaveDTO(); + param.setName("客户A"); + param.setSocietycreditcode("91450000MA5Q1G1M59"); + param.setEntryGroupstandard(List.of(new BfiCustomerGroupEntryDTO())); + BfiBillSaveResultVO result = service.saveCustomer(param); + assertEquals("1", result.getSuccessCount()); + ArgumentCaptor captor = + ArgumentCaptor.forClass(org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerSaveBodyDTO.class); + verify(client).customerSave(eq("token-1"), captor.capture()); + assertEquals(param, captor.getValue().getData().get(0)); + } + + @Test + void saveApBillShouldValidateRequiredFields() { + BfiApBillSaveDTO noSrc = new BfiApBillSaveDTO(); + assertThrows(BfiException.class, () -> service.saveApBill(noSrc)); + + BfiApBillSaveDTO noEntry = new BfiApBillSaveDTO(); + noEntry.setAwrpSrcSys("WCCK"); + noEntry.setAwrpSrcCode("AP-1"); + assertThrows(BfiException.class, () -> service.saveApBill(noEntry)); + verifyNoInteractions(client); + } + + @Test + void saveApBillShouldWrapData() { + mockAccessToken(); + when(client.apBillSave(anyString(), any())).thenReturn(success(saveResult(1))); + BfiApBillSaveDTO param = new BfiApBillSaveDTO(); + param.setAwrpSrcSys("WCCK"); + param.setAwrpSrcCode("AP-1"); + param.setDetailentry(List.of(new BfiApBillSaveEntryDTO())); + assertEquals("1", service.saveApBill(param).getSuccessCount()); + } + + @Test + void queryApBillShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.apBillQuery(eq("token-1"), eq(1), eq(10), any(), any(), any(), any(), any(), any())) + .thenReturn(success(page)); + BfiApBillQueryDTO param = new BfiApBillQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + assertEquals(page, service.queryApBill(param)); + } + + @Test + void saveArBillShouldValidateRequiredFields() { + BfiArBillSaveDTO noSrc = new BfiArBillSaveDTO(); + assertThrows(BfiException.class, () -> service.saveArBill(noSrc)); + + BfiArBillSaveDTO noEntry = new BfiArBillSaveDTO(); + noEntry.setAwrpSrcSys("WCCK"); + noEntry.setAwrpSrcCode("AR-1"); + assertThrows(BfiException.class, () -> service.saveArBill(noEntry)); + verifyNoInteractions(client); + } + + @Test + void saveArBillShouldWrapData() { + mockAccessToken(); + when(client.arBillSave(anyString(), any())).thenReturn(success(saveResult(1))); + BfiArBillSaveDTO param = new BfiArBillSaveDTO(); + param.setAwrpSrcSys("WCCK"); + param.setAwrpSrcCode("AR-1"); + param.setEntry(List.of(new BfiArBillSaveEntryDTO())); + assertEquals("1", service.saveArBill(param).getSuccessCount()); + } + + @Test + void queryArBillShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.arBillQuery(eq("token-1"), eq(1), eq(10), any(), any(), any(), any(), any(), any())) + .thenReturn(success(page)); + BfiArBillQueryDTO param = new BfiArBillQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + assertEquals(page, service.queryArBill(param)); + } + + @Test + void invoiceAssignShouldValidateAndWrapBody() { + assertThrows(BfiException.class, () -> service.invoiceAssign(null, List.of())); + assertThrows(BfiException.class, () -> service.invoiceAssign("assign", List.of())); + + mockAccessToken(); + when(client.invoiceAssign(anyString(), any())).thenReturn(success(saveResult(1))); + BfiInvoiceAssignRefDTO invoice = new BfiInvoiceAssignRefDTO(); + invoice.setAwrpSrcCode("INV-1"); + invoice.setAwrpSrcSys("WCCK"); + BfiInvoiceAssignRefDTO apBill = new BfiInvoiceAssignRefDTO(); + apBill.setAwrpSrcCode("AP-1"); + apBill.setAwrpSrcSys("WCCK"); + BfiInvoiceAssignItemDTO item = new BfiInvoiceAssignItemDTO(); + item.setApInvoice(List.of(invoice)); + item.setApFinapbill(List.of(apBill)); + assertEquals("1", service.invoiceAssign("assign", List.of(item)).getSuccessCount()); + ArgumentCaptor captor = ArgumentCaptor.forClass(BfiInvoiceAssignBodyDTO.class); + verify(client).invoiceAssign(eq("token-1"), captor.capture()); + assertEquals("assign", captor.getValue().getOp()); + } + + @Test + void saveInvoiceApplyShouldValidateRequiredFields() { + BfiInvoiceApplySaveDTO noBillNo = new BfiInvoiceApplySaveDTO(); + assertThrows(BfiException.class, () -> service.saveInvoiceApply(noBillNo)); + + BfiInvoiceApplySaveDTO noItem = new BfiInvoiceApplySaveDTO(); + noItem.setBillno("KPSQ-1"); + noItem.setOrgidNumber("01.00"); + assertThrows(BfiException.class, () -> service.saveInvoiceApply(noItem)); + verifyNoInteractions(client); + } + + @Test + void saveInvoiceApplyShouldWrapData() { + mockAccessToken(); + when(client.invoiceApplySave(anyString(), any())).thenReturn(success(saveResult(1))); + BfiInvoiceApplySaveDTO param = new BfiInvoiceApplySaveDTO(); + param.setBillno("KPSQ-1"); + param.setOrgidNumber("01.00"); + param.setSimOriginalBillItem(List.of(new BfiInvoiceApplySaveEntryDTO())); + assertEquals("1", service.saveInvoiceApply(param).getSuccessCount()); + } + + @Test + void queryInvoiceApplyShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.invoiceApplyQuery(eq("token-1"), eq(1), eq(10), any(), any(), any(), any())) + .thenReturn(success(page)); + BfiInvoiceApplyQueryDTO param = new BfiInvoiceApplyQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + assertEquals(page, service.queryInvoiceApply(param)); + } + + @Test + void queryInvoiceApplyInvoiceShouldEncodeBase64Data() { + mockAccessToken(); + BfiOpenApiResultVO> openApiResult = new BfiOpenApiResultVO<>(); + openApiResult.setSuccess(true); + openApiResult.setErrorCode("S0000"); + openApiResult.setData(List.of()); + when(client.invoiceApplyOpenApi(anyString(), any())).thenReturn(openApiResult); + BfiInvoiceApplyOpenApiQueryDTO param = new BfiInvoiceApplyOpenApiQueryDTO(); + param.setSerialNo("KPSQ-1,KPSQ-2"); + param.setSellerTaxpayerId("91450000MA5Q1G1M59"); + service.queryInvoiceApplyInvoice(param); + ArgumentCaptor captor = + ArgumentCaptor.forClass(org.springblade.thirdparty.bfi.pojo.dto.BfiInvoiceApplyOpenApiBodyDTO.class); + verify(client).invoiceApplyOpenApi(eq("token-1"), captor.capture()); + assertEquals("BILL.INVOICE.QUERY", captor.getValue().getInterfaceCode()); + assertEquals("test-client", captor.getValue().getBusinessSystemCode()); + String decoded = new String(Base64.getDecoder().decode(captor.getValue().getData()), StandardCharsets.UTF_8); + JSONObject json = JSONUtil.parseObj(decoded); + assertEquals("KPSQ-1,KPSQ-2", json.getStr("serialNo")); + assertEquals("91450000MA5Q1G1M59", json.getStr("sellerTaxpayerId")); + } + + @Test + void queryInvoiceApplyInvoiceShouldThrowWhenParamsBlank() { + assertThrows(BfiException.class, () -> service.queryInvoiceApplyInvoice(new BfiInvoiceApplyOpenApiQueryDTO())); + verifyNoInteractions(client); + } + + @Test + void saveReceivedInvoiceShouldValidateRequiredFields() { + BfiReceivedInvoiceSaveDTO noSrc = new BfiReceivedInvoiceSaveDTO(); + assertThrows(BfiException.class, () -> service.saveReceivedInvoice(noSrc)); + + BfiReceivedInvoiceSaveDTO noEntry = new BfiReceivedInvoiceSaveDTO(); + noEntry.setAwrpSrcSys("WCCK"); + noEntry.setAwrpSrcCode("INV-1"); + assertThrows(BfiException.class, () -> service.saveReceivedInvoice(noEntry)); + verifyNoInteractions(client); + } + + @Test + void saveReceivedInvoiceShouldWrapData() { + mockAccessToken(); + when(client.receivedInvoiceSave(anyString(), any())).thenReturn(success(saveResult(1))); + BfiReceivedInvoiceSaveDTO param = new BfiReceivedInvoiceSaveDTO(); + param.setAwrpSrcSys("WCCK"); + param.setAwrpSrcCode("INV-1"); + param.setEntry(List.of(new BfiReceivedInvoiceSaveEntryDTO())); + assertEquals("1", service.saveReceivedInvoice(param).getSuccessCount()); + } + + @Test + void queryReceivedInvoiceShouldValidateModifyTime() { + assertThrows(BfiException.class, () -> service.queryReceivedInvoice(new BfiReceivedInvoiceQueryDTO())); + verifyNoInteractions(client); + } + + @Test + void queryReceivedInvoiceShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.receivedInvoiceQuery(anyString(), any(BfiReceivedInvoiceQueryDTO.class))).thenReturn(success(page)); + BfiReceivedInvoiceQueryDTO param = new BfiReceivedInvoiceQueryDTO(); + param.setModifytime("2026-09-08 10:36:29"); + param.setModifytimeE("2026-09-08 10:39:36"); + assertEquals(page, service.queryReceivedInvoice(param)); + } + + @Test + void queryRecBillShouldValidateRequiredFields() { + assertThrows(BfiException.class, () -> service.queryRecBill(new BfiRecBillQueryDTO())); + + BfiRecBillQueryDTO noDate = new BfiRecBillQueryDTO(); + noDate.setPageNo(1); + noDate.setPageSize(10); + assertThrows(BfiException.class, () -> service.queryRecBill(noDate)); + verifyNoInteractions(client); + } + + @Test + void queryRecBillShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.recBillQuery(eq("token-1"), eq(1), eq(10), any(), any(), any(), any())) + .thenReturn(success(page)); + BfiRecBillQueryDTO param = new BfiRecBillQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + param.setBeginBizdate("2026-08-08"); + param.setEndBizdate("2026-09-08"); + assertEquals(page, service.queryRecBill(param)); + } + + @Test + void queryClaimAnnounceShouldValidateParams() { + assertThrows(BfiException.class, () -> service.queryClaimAnnounce(null, 1, 10)); + assertThrows(BfiException.class, () -> service.queryClaimAnnounce("张三", null, 10)); + } + + @Test + void queryClaimAnnounceShouldReturnPage() { + mockAccessToken(); + BfiPageVO page = new BfiPageVO<>(); + when(client.claimAnnounceQuery("token-1", "张三", 1, 10)).thenReturn(success(page)); + assertEquals(page, service.queryClaimAnnounce("张三", 1, 10)); + } + + @Test + void pushClaimResultShouldValidateRequiredFields() { + assertThrows(BfiException.class, () -> service.pushClaimResult(null)); + + BfiClaimPushDTO noBillId = new BfiClaimPushDTO(); + assertThrows(BfiException.class, () -> service.pushClaimResult(noBillId)); + + BfiClaimPushDTO noEntry = new BfiClaimPushDTO(); + noEntry.setBillid(1L); + noEntry.setAwrpSrcSys("WCCK"); + noEntry.setAwrpSrcCode("RL-1"); + assertThrows(BfiException.class, () -> service.pushClaimResult(noEntry)); + verifyNoInteractions(client); + } + + @Test + void pushClaimResultShouldWrapData() { + mockAccessToken(); + when(client.claimBillPush(anyString(), any())).thenReturn(success(saveResult(1))); + BfiClaimPushDTO param = new BfiClaimPushDTO(); + param.setBillid(2398805822369971200L); + param.setAwrpSrcSys("WCCK"); + param.setAwrpSrcCode("RL-1"); + param.setEntryentity(List.of(new BfiClaimPushEntryDTO())); + assertEquals("1", service.pushClaimResult(param).getSuccessCount()); + } + + @Test + void queryInvoicePoolShouldValidateQueryParam() { + assertThrows(BfiException.class, () -> service.queryInvoicePool(new BfiInvoicePoolQueryDTO())); + verifyNoInteractions(client); + } + + @Test + void queryInvoicePoolShouldReturnRows() { + mockAccessToken(); + BfiInvoicePoolVO invoice = new BfiInvoicePoolVO(); + when(client.invoicePoolQuery(anyString(), any(BfiInvoicePoolQueryDTO.class))) + .thenReturn(success(List.of(invoice))); + BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO(); + param.setQueryParam(Map.of("invoiceNo", "25532000000044538098")); + List rows = service.queryInvoicePool(param); + assertEquals(1, rows.size()); + } + + @Test + void downloadInvoiceShouldValidatePath() { + assertThrows(BfiException.class, () -> service.downloadInvoice(null)); + verifyNoInteractions(client); + } + + @Test + void downloadInvoiceShouldThrowWhenStatusNotOk() { + mockAccessToken(); + Response response = downloadResponse(500, "Internal Error"); + when(client.invoiceDownload(anyString(), any())).thenReturn(response); + assertThrows(BfiException.class, () -> service.downloadInvoice("234e244b2c803400")); + response.close(); + } + + @Test + void downloadInvoiceShouldReturnResponse() { + mockAccessToken(); + Response response = downloadResponse(200, "OK"); + when(client.invoiceDownload(anyString(), any())).thenReturn(response); + assertEquals(response, service.downloadInvoice("234e244b2c803400")); + response.close(); + } + + /** + * 构建下载响应 + */ + private Response downloadResponse(int status, String reason) { + Request request = Request.create(Request.HttpMethod.POST, "/ierp/kapi/v2/awrp/bosext/attachment/download", + Map.of(), null, StandardCharsets.UTF_8); + return Response.builder().status(status).reason(reason).request(request).build(); + } + + @Test + void commonCallShouldThrowWhenRemoteFailed() { + mockAccessToken(); + BfiResultVO> failed = new BfiResultVO<>(); + failed.setStatus(false); + failed.setErrorCode("400"); + failed.setMessage("操作失败"); + when(client.customerQuery(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(failed); + BfiCustomerQueryDTO param = new BfiCustomerQueryDTO(); + param.setPageNo(1); + param.setPageSize(10); + BfiException exception = assertThrows(BfiException.class, () -> service.queryCustomer(param)); + assertTrue(exception.getMessage().contains("操作失败")); + } + + @Test + void getAccessTokenShouldNotCallRemoteWhenCached() { + when(bladeRedis.get("blade:third:bfi:token")).thenReturn("cached-token"); + service.getAccessToken(); + verify(client, never()).getToken(any()); + } +}