t push
This commit is contained in:
quyixiao 2026-06-09 01:18:14 +08:00
commit 86d66f6d6b
8 changed files with 253 additions and 149 deletions

View File

@ -55,6 +55,34 @@ public class BaseController {
return value == null || value.trim().length() == 0; return value == null || value.trim().length() == 0;
} }
/**
* 规范化 base64 图片输入兼容多种常见格式
* <ul>
* <li>data:image/png;base64,xxxxData URI 格式自动剥离前缀</li>
* <li>data:image/jpeg;base64,xxxx同理</li>
* <li> base64 字符串直接保留</li>
* <li>含换行/空白字符的 base64自动清除</li>
* </ul>
*
* @param imageBase64 原始输入
* @return 清理后的纯 base64 字符串
*/
protected String normalizeBase64Image(String imageBase64) {
if (imageBase64 == null) {
return null;
}
// 剥离 data:image/xxx;base64, 前缀
String value = imageBase64.trim();
if (value.regionMatches(true, 0, "data:", 0, 5)) {
int commaIdx = value.indexOf(',');
if (commaIdx >= 0) {
value = value.substring(commaIdx + 1);
}
}
// 清除 base64 中常见的换行和空白
return value.replaceAll("[\\s\\r\\n]", "");
}
protected Map<String, Object> requestBaidu(String uri, String content) { protected Map<String, Object> requestBaidu(String uri, String content) {
String result = null; String result = null;
try { try {

View File

@ -5,12 +5,15 @@ import com.heyu.api.baidu.request.doc.BDocClassifyRequest;
import com.heyu.api.baidu.response.doc.BDocClassifyResp; import com.heyu.api.baidu.response.doc.BDocClassifyResp;
import com.heyu.api.controller.BaseController; import com.heyu.api.controller.BaseController;
import com.heyu.api.data.annotation.CacheResult; import com.heyu.api.data.annotation.CacheResult;
import com.heyu.api.data.annotation.EbAuthentication;
import com.heyu.api.data.annotation.NotIntercept; import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.R;
import com.heyu.api.data.utils.StringUtils; import com.heyu.api.data.utils.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.net.URLEncoder;
import java.util.Map; import java.util.Map;
/*** /***
@ -41,11 +44,17 @@ public class DocClassifyController extends BaseController {
*/ */
@RequestMapping("/classify") @RequestMapping("/classify")
@CacheResult @CacheResult
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
public R<BDocClassifyResp> classify(BDocClassifyRequest request) { public R<BDocClassifyResp> classify(BDocClassifyRequest request) {
if (request == null || (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl()))) { if (request == null || (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl()))) {
return R.error("image 和 url 不能都为空"); return R.error("image 和 url 不能都为空");
} }
String content = buildContent(request); String content;
try {
content = buildContent(request);
} catch (Exception e) {
return R.error("参数编码失败");
}
Map<String, Object> result = requestBaidu(DOC_CLASSIFY_URI, content); Map<String, Object> result = requestBaidu(DOC_CLASSIFY_URI, content);
if (result == null) { if (result == null) {
return R.error("识别失败"); return R.error("识别失败");
@ -55,13 +64,13 @@ public class DocClassifyController extends BaseController {
return R.ok().setData(resp); return R.ok().setData(resp);
} }
private String buildContent(BDocClassifyRequest request) { private String buildContent(BDocClassifyRequest request) throws Exception {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (StringUtils.isNotBlank(request.getImageBase64())) { if (StringUtils.isNotBlank(request.getImageBase64())) {
sb.append("&image=").append(request.getImageBase64()); sb.append("&image=").append(URLEncoder.encode(normalizeBase64Image(request.getImageBase64()), "UTF-8"));
} }
if (StringUtils.isNotBlank(request.getImageUrl())) { if (StringUtils.isNotBlank(request.getImageUrl())) {
sb.append("&url=").append(request.getImageUrl()); sb.append("&url=").append(URLEncoder.encode(request.getImageUrl(), "UTF-8"));
} }
return sb.toString(); return sb.toString();
} }

View File

@ -1,23 +1,21 @@
package com.heyu.api.controller.doc; package com.heyu.api.controller.doc;
import com.heyu.api.baidu.handle.doc.BForgeryDetectionHandle; import com.alibaba.fastjson.JSONObject;
import com.heyu.api.baidu.request.doc.BForgeryDetectionRequest;
import com.heyu.api.baidu.response.doc.BForgeryDetectionResp; import com.heyu.api.baidu.response.doc.BForgeryDetectionResp;
import com.heyu.api.controller.BaseController;
import com.heyu.api.data.annotation.EbAuthentication; import com.heyu.api.data.annotation.EbAuthentication;
import com.heyu.api.data.annotation.NotIntercept; import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.constants.ApiConstants; import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.R;
import com.heyu.api.data.utils.StringUtils;
import com.heyu.api.request.doc.ForgeryDetectionRequest; import com.heyu.api.request.doc.ForgeryDetectionRequest;
import com.heyu.api.resp.doc.ForgeryDetectionResp;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList; import java.net.URLEncoder;
import java.util.List; import java.util.Map;
/** /**
* 图片篡改检测 * 图片篡改检测
@ -27,82 +25,59 @@ import java.util.List;
* 支持对图像中的伪造区域以热力图形式进行可视化返回 * 支持对图像中的伪造区域以热力图形式进行可视化返回
* *
* 百度文档https://cloud.baidu.com/doc/OCR/s/kmfdnccok * 百度文档https://cloud.baidu.com/doc/OCR/s/kmfdnccok
*
* @author zhengli
* @since 20260607_zl
*/ */
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/doc") @RequestMapping("/doc")
@NotIntercept @NotIntercept
public class ForgeryDetectionController { public class ForgeryDetectionController extends BaseController {
@Autowired private static final String FORGERY_DETECTION_URI = "rest/2.0/ocr/v1/forgery_detection";
private BForgeryDetectionHandle bForgeryDetectionHandle;
/** /**
* 图片篡改检测 * 图片篡改检测
* @param request: {"detectProportion":"true","detectThreshold":"0.9887","imageUrl":"https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png","restrictProbability":"0.8","returnHeatmap":"true"} *
* @return * 假设(Given) + (When) + (Then):
* - Given: 传入 imageBase64 imageUrl二选一
* - When: 调用百度篡改检测API使用默认参数
* - Then: 返回篡改检测结果包含 detectionResulttamperedLocation
*
* @param request {"imageBase64": "...", "imageUrl": "..."}
* @return 篡改检测结果
*/ */
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH) @EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
@PostMapping("/forgeryDetection") @PostMapping("/forgeryDetection")
public R<ForgeryDetectionResp> forgeryDetection(ForgeryDetectionRequest request) { public R<BForgeryDetectionResp> forgeryDetection(ForgeryDetectionRequest request) {
long start = System.currentTimeMillis(); if (request == null || (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl()))) {
return R.error("image 和 url 不能都为空");
BForgeryDetectionRequest bRequest = toBaiduRequest(request);
ApiR<BForgeryDetectionResp> bR = bForgeryDetectionHandle.handle(bRequest);
if (!bR.isSuccess()) {
log.info("图片篡改检测-失败, error:{}, 耗时:{}ms", bR.getErrorMsg(), System.currentTimeMillis() - start);
return R.error(bR.getErrorMsg());
} }
String content;
BForgeryDetectionResp bResp = bR.getData(); try {
if (bResp.getResult() == null) { content = buildContent(request);
log.info("图片篡改检测-结果为空, 耗时:{}ms", System.currentTimeMillis() - start); } catch (Exception e) {
return R.error("图片篡改检测结果为空"); log.error("forgeryDetection buildContent 异常", e);
return R.error("参数编码失败");
} }
Map<String, Object> result = requestBaidu(FORGERY_DETECTION_URI, content);
ForgeryDetectionResp resp = toResp(bResp); if (result == null) {
return R.error("识别失败");
log.info("图片篡改检测-完成, 耗时:{}ms", System.currentTimeMillis() - start); }
BForgeryDetectionResp resp = JSONObject.parseObject(
JSONObject.toJSONString(result), BForgeryDetectionResp.class);
return R.ok().setData(resp); return R.ok().setData(resp);
} }
private BForgeryDetectionRequest toBaiduRequest(ForgeryDetectionRequest request) { private String buildContent(ForgeryDetectionRequest request) throws Exception {
BForgeryDetectionRequest bRequest = new BForgeryDetectionRequest(); StringBuilder sb = new StringBuilder();
if (request == null) { if (StringUtils.isNotBlank(request.getImageBase64())) {
return bRequest; sb.append("&image=").append(URLEncoder.encode(normalizeBase64Image(request.getImageBase64()), "UTF-8"));
} }
bRequest.setImageBase64(request.getImageBase64()); if (StringUtils.isNotBlank(request.getImageUrl())) {
bRequest.setImageUrl(request.getImageUrl()); sb.append("&url=").append(URLEncoder.encode(request.getImageUrl(), "UTF-8"));
bRequest.setDetectProportion(request.getDetectProportion());
bRequest.setDetectThreshold(request.getDetectThreshold());
bRequest.setReturnHeatmap(request.getReturnHeatmap());
bRequest.setRestrictProbability(request.getRestrictProbability());
return bRequest;
}
private ForgeryDetectionResp toResp(BForgeryDetectionResp bResp) {
ForgeryDetectionResp resp = new ForgeryDetectionResp();
BForgeryDetectionResp.ResultDTO result = bResp.getResult();
resp.setDetectionResult(result.getDetectionResult());
resp.setTamperedProportion(result.getTamperedProportion());
resp.setHeatmap(result.getHeatmap());
if (result.getTamperedLocation() != null) {
List<ForgeryDetectionResp.TamperedLocation> locations = new ArrayList<>();
for (BForgeryDetectionResp.TamperedLocationDTO dto : result.getTamperedLocation()) {
ForgeryDetectionResp.TamperedLocation location = new ForgeryDetectionResp.TamperedLocation();
location.setLeft(dto.getLeft());
location.setTop(dto.getTop());
location.setWidth(dto.getWidth());
location.setHeight(dto.getHeight());
location.setProbability(dto.getProbability());
locations.add(location);
}
resp.setTamperedLocation(locations);
} }
return sb.toString();
return resp;
} }
} }

View File

@ -4,6 +4,9 @@ import lombok.Data;
/** /**
* 图片篡改检测 - 前端请求参数 * 图片篡改检测 - 前端请求参数
*
* @author zhengli
* @since 20260607_zl
*/ */
@Data @Data
public class ForgeryDetectionRequest { public class ForgeryDetectionRequest {
@ -19,28 +22,4 @@ public class ForgeryDetectionRequest {
* imageBase64 二选一 * imageBase64 二选一
*/ */
private String imageUrl; private String imageUrl;
/**
* 是否返回图片篡改置信度
* - true返回
* - false不返回默认
*/
private String detectProportion;
/**
* 图片篡改检出阈值范围0.00011默认为0.9887
*/
private String detectThreshold;
/**
* 是否返回伪造区域热力图
* - true返回热力图base64编码
* - false不返回默认
*/
private String returnHeatmap;
/**
* 返回伪造区域坐标的阈值范围0.11默认为0.8
*/
private String restrictProbability;
} }

View File

@ -0,0 +1,20 @@
package com;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class TestConstant {
public static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png";
public static final String TARGET_IMAGE_BASE64;
static {
try {
Path path = Paths.get("src/test/resources/image_base64.txt");
TARGET_IMAGE_BASE64 = "data:image/png;base64," + new String(Files.readAllBytes(path), StandardCharsets.UTF_8).trim();
} catch (Exception e) {
throw new RuntimeException("Failed to load image_base64.txt", e);
}
}
}

View File

@ -1,6 +1,7 @@
package com.heyu.api.controller.doc; package com.heyu.api.controller.doc;
import com.ApiInterfaceApplicationTests; import com.ApiInterfaceApplicationTests;
import com.TestConstant;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.heyu.api.baidu.request.doc.BDocClassifyRequest; import com.heyu.api.baidu.request.doc.BDocClassifyRequest;
import com.heyu.api.baidu.response.doc.BDocClassifyResp; import com.heyu.api.baidu.response.doc.BDocClassifyResp;
@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* 文件检测分类 - 在线图片验证 * 文件检测分类 - 在线图片验证
@ -28,13 +30,12 @@ public class DocClassifyControllerTest extends ApiInterfaceApplicationTests {
@Autowired @Autowired
private DocClassifyController docClassifyController; private DocClassifyController docClassifyController;
private static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png";
@Test @Test
void classifyByUrlTest() { void classifyByUrlTest() {
// 1. 构造请求 // 1. 构造请求
BDocClassifyRequest request = new BDocClassifyRequest(); BDocClassifyRequest request = new BDocClassifyRequest();
request.setImageUrl(TARGET_IMAGE_URL); request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
// 2. 打印请求参数 // 2. 打印请求参数
System.out.println("\n========== 请求参数 =========="); System.out.println("\n========== 请求参数 ==========");
@ -75,4 +76,73 @@ public class DocClassifyControllerTest extends ApiInterfaceApplicationTests {
assertNotNull(result, "返回结果不能为空"); assertNotNull(result, "返回结果不能为空");
assertEquals("400", result.getCode(), "参数为空时应返回失败"); assertEquals("400", result.getCode(), "参数为空时应返回失败");
} }
/**
* 假设(Given): 本地存在 base64 编码的测试图片
* (When): 调用 classify 接口传入 imageBase64 参数
* (Then): 返回成功的分类检测结果
*/
@Test
void classifyByBase64Test() {
// 1. 构造请求 - 使用 base64 图片
BDocClassifyRequest request = new BDocClassifyRequest();
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
// 2. 调用接口
R<BDocClassifyResp> result = docClassifyController.classify(request);
// 3. 断言
assertNotNull(result, "返回结果不能为空");
assertEquals("200", result.getCode(), "base64 传图应返回成功");
assertNotNull(result.getData(), "返回数据不能为空");
System.out.println("\n========== base64 分类结果 ==========");
System.out.println(JSON.toJSONString(result));
System.out.println("====================================");
}
/**
* 假设(Given): 同时传入 imageBase64 imageUrl
* (When): 调用 classify 接口
* (Then): 接口正常返回成功image 优先级更高
*/
@Test
void classifyByBase64AndUrlBothTest() {
// 1. 构造请求 - 同时传入 base64 url
BDocClassifyRequest request = new BDocClassifyRequest();
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
// 2. 调用接口
R<BDocClassifyResp> result = docClassifyController.classify(request);
// 3. 断言
assertNotNull(result, "返回结果不能为空");
assertEquals("200", result.getCode(), "同时传 base64 和 url 应返回成功");
assertNotNull(result.getData(), "返回数据不能为空");
}
/**
* 假设(Given): imageBase64 传入无效数据 base64 字符串
* (When): 调用 classify 接口
* (Then): 百度 API 返回识别失败
*/
@Test
void classifyByInvalidBase64Test() {
// 1. 构造请求 - 传入无效 base64
BDocClassifyRequest request = new BDocClassifyRequest();
request.setImageBase64("invalid_base64_data_not_an_image");
// 2. 调用接口
R<BDocClassifyResp> result = docClassifyController.classify(request);
// 3. 断言 - 百度 API 会返回错误接口应包装为非200或返回错误信息
assertNotNull(result, "返回结果不能为空");
// 无效图片百度会返回错误码不一定是200
assertTrue(result.getCode() != null, "返回 code 不能为空");
System.out.println("\n========== 无效 base64 结果 ==========");
System.out.println(JSON.toJSONString(result));
System.out.println("=====================================");
}
} }

View File

@ -1,10 +1,10 @@
package com.heyu.api.controller.doc; package com.heyu.api.controller.doc;
import com.ApiInterfaceApplicationTests; import com.ApiInterfaceApplicationTests;
import com.alibaba.fastjson.JSON; import com.TestConstant;
import com.heyu.api.baidu.response.doc.BForgeryDetectionResp;
import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.R;
import com.heyu.api.request.doc.ForgeryDetectionRequest; import com.heyu.api.request.doc.ForgeryDetectionRequest;
import com.heyu.api.resp.doc.ForgeryDetectionResp;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -12,75 +12,97 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* 图片篡改检测 - 在线图片验证 * 图片篡改检测 - 单元测试
*
* 调用本地 /doc/forgeryDetection 接口验证目标图片是否被篡改
*
* 假设(Given): 目标图片可访问百度 API 可用
* (When): 调用 forgeryDetection 接口所有参数开启
* (Then): 返回检测结果
* *
* @author zhengli * @author zhengli
* @since 20260528_zl * @since 20260607_zl
*/ */
public class ForgeryDetectionControllerTest extends ApiInterfaceApplicationTests { public class ForgeryDetectionControllerTest extends ApiInterfaceApplicationTests {
@Autowired @Autowired
private ForgeryDetectionController forgeryDetectionController; private ForgeryDetectionController forgeryDetectionController;
private static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png"; /**
* 验证传入 imageUrl 调用百度篡改检测使用默认参数
*
* 假设(Given): 百度 API 可用目标图片可访问
* (When): 只传 imageUrl不传可选参数
* (Then): 返回 code=200data nullresult 中有 detectionResult
*/
@Test @Test
void forgeryDetectionAllParamsTest() { void forgeryDetectionWithImageUrlTest() {
// 1. 构造请求 - 所有参数开启 // Arrange
ForgeryDetectionRequest request = new ForgeryDetectionRequest(); ForgeryDetectionRequest request = new ForgeryDetectionRequest();
request.setImageUrl(TARGET_IMAGE_URL); request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
request.setDetectProportion("true");
request.setDetectThreshold("0.9887");
request.setReturnHeatmap("true");
request.setRestrictProbability("0.8");
// 2. 打印请求参数 // Act
System.out.println("\n========== 请求参数 =========="); R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
System.out.println(JSON.toJSONString(request));
System.out.println("==============================");
// 3. 调用本地 /doc/forgeryDetection 接口 // Assert
R<ForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
// 4. 打印响应结果
System.out.println("\n========== 响应结果 ==========");
System.out.println(JSON.toJSONString(result));
System.out.println("==============================");
// 5. 断言
assertNotNull(result, "返回结果不能为空"); assertNotNull(result, "返回结果不能为空");
assertEquals("200", result.getCode(), "接口应返回成功"); assertEquals("200", result.getCode(), "接口应返回成功");
assertNotNull(result.getData(), "返回数据不能为空"); assertNotNull(result.getData(), "返回数据不能为空");
assertNotNull(result.getData().getResult(), "百度返回的 result 不能为空");
assertNotNull(result.getData().getResult().getDetectionResult(), "检测结果 detectionResult 不能为空");
}
// 6. 打印接口返回值 /**
ForgeryDetectionResp data = result.getData(); * 验证传入 imageBase64 调用百度篡改检测使用默认参数
String heatmapDisplay = data.getHeatmap() != null *
? data.getHeatmap().substring(0, Math.min(50, data.getHeatmap().length())) + "...(共" + data.getHeatmap().length() + "字符)" * 假设(Given): 百度 API 可用imageBase64 为有效图片
: "null"; * (When): 只传 imageBase64不传可选参数
* (Then): 返回 code=200data nullresult 中有 detectionResult
*/
@Test
void forgeryDetectionWithImageBase64Test() {
ForgeryDetectionRequest request = new ForgeryDetectionRequest();
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
System.out.println("\n========== /doc/forgeryDetection 接口返回 =========="); // Act
System.out.println("{\"code\":\"" + result.getCode() + "\","); R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
System.out.println(" \"msg\":\"" + result.getMsg() + "\",");
System.out.println(" \"data\":{");
System.out.println(" \"detectionResult\":\"" + data.getDetectionResult() + "\",");
System.out.println(" \"tamperedProportion\":" + data.getTamperedProportion() + ",");
System.out.println(" \"heatmap\":\"" + heatmapDisplay + "\",");
System.out.println(" \"tamperedLocation\":" + JSON.toJSONString(data.getTamperedLocation()));
System.out.println(" }");
System.out.println("}");
System.out.println("====================================================");
// 结论 // Assert
if ("fake".equals(data.getDetectionResult())) { assertNotNull(result, "返回结果不能为空");
System.out.println(">>> 结论: 图片【已被篡改】,篡改置信度: " + data.getTamperedProportion()); assertEquals("200", result.getCode(), "接口应返回成功");
} else { assertNotNull(result.getData(), "返回数据不能为空");
System.out.println(">>> 结论: 图片【未被篡改】,篡改置信度: " + data.getTamperedProportion()); assertNotNull(result.getData().getResult(), "百度返回的 result 不能为空");
} assertNotNull(result.getData().getResult().getDetectionResult(), "检测结果 detectionResult 不能为空");
}
/**
* 验证image url 都为空时返回错误
*
* 假设(Given): 不传 imageBase64 也不传 imageUrl
* (When): 调用接口
* (Then): 返回 code=400msg 包含错误信息
*/
@Test
void forgeryDetectionEmptyParamsTest() {
// Arrange
ForgeryDetectionRequest request = new ForgeryDetectionRequest();
// Act
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
// Assert
assertNotNull(result, "返回结果不能为空");
assertEquals("400", result.getCode(), "参数为空应返回 400");
}
/**
* 验证request null 时返回错误
*
* 假设(Given): request null
* (When): 调用接口
* (Then): 返回 code=400
*/
@Test
void forgeryDetectionNullRequestTest() {
// Act
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(null);
// Assert
assertNotNull(result, "返回结果不能为空");
assertEquals("400", result.getCode(), "request 为 null 应返回 400");
} }
} }

File diff suppressed because one or more lines are too long