task-146: collectdata 自洽行为契约(后端无 file 字段 VO 快照、前端 success+downloadUrl 判定含空白边界)+ 前后端 13 条测试

This commit is contained in:
2026-09-02 05:55:43 +08:00
parent 0945882458
commit eced873779
3 changed files with 163 additions and 0 deletions
@@ -0,0 +1,102 @@
package com.nanri.aiimage.modules.task.contract;
import com.nanri.aiimage.modules.collectdata.model.vo.CollectDataHistoryItemVo;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
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-146collectdata 自洽行为契约(plan 08)。
* 后端 history VO 不返回 file 阶段字段(fileStatus/fileReady/fileError);
* 下载语义由 success + downloadUrl 推导(任务 SUCCESS 且有结果文件才可下载);
* 进度展示字段自洽。
*/
class CollectDataSelfConsistencyTest {
private static Map<String, Class<?>> fieldsOf(Class<?> type) {
return Arrays.stream(type.getDeclaredFields())
.filter(field -> !java.lang.reflect.Modifier.isStatic(field.getModifiers()))
.collect(Collectors.toMap(Field::getName, Field::getType));
}
@Test
void backendHasNoFilePhaseFields() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertFalse(fields.containsKey("fileStatus"), "collectdata 不返回 fileStatus");
assertFalse(fields.containsKey("fileReady"), "collectdata 不返回 fileReady");
assertFalse(fields.containsKey("fileError"), "collectdata 不返回 fileError");
assertFalse(fields.containsKey("fileProgressPercent"), "collectdata 不返回 fileProgressPercent");
}
@Test
void downloadFieldsPresent() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertEquals(String.class, fields.get("downloadUrl"), "downloadUrl 字段存在");
assertEquals(Boolean.class, fields.get("success"), "success 字段存在");
}
@Test
void statusFlowFieldsPresent() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertEquals(String.class, fields.get("taskStatus"), "taskStatus 字段存在");
assertEquals(String.class, fields.get("error"), "error 字段存在");
assertEquals(Long.class, fields.get("taskId"));
assertEquals(Long.class, fields.get("resultId"));
}
@Test
void progressDisplayFieldsPresent() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertEquals(Integer.class, fields.get("dedupeFilteredCount"), "进度展示字段存在");
assertEquals(Integer.class, fields.get("invalidFilteredCount"));
assertEquals(Integer.class, fields.get("brandRejectedCount"));
assertEquals(Integer.class, fields.get("finalRowCount"));
assertEquals(Integer.class, fields.get("rowCount"));
}
@Test
void successAndUrlAreTheOnlyDownloadSignals() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
// 可下载信号仅 success + downloadUrl(无 fileReady 类独立标志)
assertTrue(fields.containsKey("success"));
assertTrue(fields.containsKey("downloadUrl"));
assertFalse(fields.containsKey("fileReady"));
}
@Test
void fileFieldsAbsentEvenInSharedLightVoContract() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertFalse(fields.containsKey("fileJobId"), "collectdata 无 fileJobId");
assertFalse(fields.containsKey("fileJobStatus"), "collectdata 无 fileJobStatus");
}
@Test
void historyIdentityFieldsPresent() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
assertEquals(String.class, fields.get("sourceFilename"));
assertEquals(String.class, fields.get("resultFilename"));
assertEquals(String.class, fields.get("taskNo"));
}
@Test
void contractFrozenFieldSet() {
Map<String, Class<?>> fields = fieldsOf(CollectDataHistoryItemVo.class);
// 快照:字段集合固定(下载用 success+downloadUrl,无 file 阶段字段)
java.util.Set<String> expected = java.util.Set.of(
"resultId", "taskId", "taskNo", "sourceFilename", "resultFilename", "downloadUrl",
"taskStatus", "success", "error", "rowCount", "dedupeFilteredCount",
"invalidFilteredCount", "brandRejectedCount", "finalRowCount",
"taskType", "progressPercent", "totalRows", "receivedRows", "processedRows",
"collectStage", "currentKeyword", "searchCurrentPage", "searchTotalPages",
"detailProcessedAsins", "detailTotalAsins", "filters",
"createdAt", "startedAt", "finishedAt");
assertEquals(expected, fields.keySet(), "collectdata history VO 字段集合冻结");
}
}