From f0f9ba29f0b7cab88f0c9e223420a2cafaf6218a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Sat, 5 Sep 2026 09:00:50 +0800 Subject: [PATCH] =?UTF-8?q?task-205:=20parsed-payload=20=E5=A5=91=E7=BA=A6?= =?UTF-8?q?=E5=9B=9E=E6=94=BE=EF=BC=88env-gated=EF=BC=8C=E7=9C=9F=E5=AE=9E?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=EF=BC=9A=E9=80=A0=20SIMILAR=5FASIN=20?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1+=E5=86=85=E8=81=94=E8=BD=BD=E8=8D=B7=20?= =?UTF-8?q?=E2=86=92=20success/=E9=A1=B6=E5=B1=82=E5=AD=97=E6=AE=B5=20item?= =?UTF-8?q?s/allItems/groups/headers/=E8=84=B1=E6=95=8F=20apiKey/=E8=A1=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=9B=E6=9C=AA=E7=9F=A5=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=20success:false=EF=BC=89+=20=E5=B7=B2=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E7=9C=9F=E8=B7=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...arAsinParsedPayloadContractReplayTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 backend-java/src/test/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinParsedPayloadContractReplayTest.java diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinParsedPayloadContractReplayTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinParsedPayloadContractReplayTest.java new file mode 100644 index 00000000..3efd2d1a --- /dev/null +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinParsedPayloadContractReplayTest.java @@ -0,0 +1,79 @@ +package com.nanri.aiimage.modules.similarasin.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * task-205:parsed-payload 契约回放(真实服务,env-gated)。 + * CONTRACT_BASE_URL + CONTRACT_DB_* 设则跑、否则跳过(CI 绿)。 + * 造 SIMILAR_ASIN 任务 + 内联解析载荷 → GET parsed-payload:success、顶层字段(items/allItems/groups/headers)、 + * 行数据、submissionId 关联字段就绪;未知任务返回 success:false(错误语义)。 + */ +class SimilarAsinParsedPayloadContractReplayTest { + + private static final long TASK_ID = 9000003L; + private static final ObjectMapper MAPPER = new ObjectMapper(); + + @Test + void parsedPayloadContract() throws Exception { + String base = System.getenv("CONTRACT_BASE_URL"); + String dbUrl = System.getenv("CONTRACT_DB_URL"); + String dbUser = System.getenv("CONTRACT_DB_USER"); + String dbPass = System.getenv("CONTRACT_DB_PASSWORD"); + Assumptions.assumeTrue(base != null && dbUrl != null && dbUser != null, "未设 CONTRACT_* 跳过"); + + seed(dbUrl, dbUser, dbPass); + HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build(); + + HttpResponse ok = get(client, base + "/api/similar-asin/tasks/" + TASK_ID + "/parsed-payload?user_id=1"); + assertEquals(200, ok.statusCode()); + JsonNode body = MAPPER.readTree(ok.body()); + assertTrue(body.path("success").asBoolean(), ok.body()); + JsonNode data = body.path("data"); + assertTrue(data.has("aiPrompt") && data.has("apiKey") && data.has("items") && data.has("allItems") + && data.has("groups") && data.has("headers"), "parsed-payload 顶层字段缺失: " + data); + assertEquals("", data.path("apiKey").asText(), "apiKey 已脱敏"); + assertTrue(data.path("items").isArray() && data.path("items").size() >= 1, "应有解析行"); + assertEquals("B0FAKETEST123", data.path("items").get(0).path("asin").asText()); + + HttpResponse unknown = get(client, base + "/api/similar-asin/tasks/999999999/parsed-payload?user_id=1"); + assertEquals(200, unknown.statusCode()); + JsonNode unknownBody = MAPPER.readTree(unknown.body()); + assertFalse(unknownBody.path("success").asBoolean(), "未知任务应 success:false"); + } + + private static void seed(String dbUrl, String user, String pass) throws Exception { + String payload = "{\"aiPrompt\":\"\",\"apiKey\":\"\",\"imgSwitch\":false," + + "\"categorySwitch\":false,\"sourceFiles\":[],\"headers\":[\"asin\",\"keyword\",\"title\"]," + + "\"items\":[{\"rowIndex\":1,\"asin\":\"B0FAKETEST123\",\"keyword\":\"ring\"}]," + + "\"groups\":[],\"allItems\":[{\"rowIndex\":1,\"asin\":\"B0FAKETEST123\",\"keyword\":\"ring\"}]}"; + try (Connection c = DriverManager.getConnection(dbUrl, user, pass); + Statement s = c.createStatement()) { + s.executeUpdate("INSERT INTO biz_file_task (id,task_no,module_type,task_mode,status,created_at,updated_at,user_id,owner_instance_id,result_json) " + + "VALUES (" + TASK_ID + ",'SA-REPLAY-" + TASK_ID + "','SIMILAR_ASIN','workbook','RUNNING',NOW(),NOW(),1,'local-smoke','" + + payload.replace("'", "''") + "') ON DUPLICATE KEY UPDATE module_type='SIMILAR_ASIN',status='RUNNING',user_id=1,result_json=VALUES(result_json)"); + } + } + + private static HttpResponse get(HttpClient client, String url) throws Exception { + return client.send(HttpRequest.newBuilder(URI.create(url)).GET() + .timeout(Duration.ofSeconds(15)).build(), + HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + } +}