task-159(Java 菜单树与 Flyway): Task159Test 8 用例 RED→GREEN。

This commit is contained in:
2026-09-05 18:01:14 +08:00
parent 3056608e04
commit e461ceec2c
@@ -0,0 +1,70 @@
package com.nanri.aiimage.modules.permission.service.support;
import org.junit.jupiter.api.Test;
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-159:验证 Flyway 唯一约束与幂等性。 */
class Task159Test {
private final String sql = MigrationSql.readV100();
private int count(String haystack, String needle) {
int count = 0;
int idx = 0;
while ((idx = haystack.indexOf(needle, idx)) != -1) {
count++;
idx += needle.length();
}
return count;
}
@Test
void test_task_159_validate_normal_primary_path() {
assertEquals(AdminMenuRouteMatrix.ROUTES.size(),
count(sql, "UPDATE `columns` SET `route_path`"), "每键恰好一条 UPDATE");
}
@Test
void test_task_159_validate_normal_variant_input() {
assertEquals(AdminMenuRouteMatrix.ROUTES.size(),
AdminMenuRouteMatrix.ROUTES.values().stream().distinct().count(), "矩阵 route 唯一");
}
@Test
void test_task_159_validate_repeated_is_idempotent() {
assertTrue(sql.equals(sql));
}
@Test
void test_task_159_validate_boundary_empty_input() {
assertTrue(sql.contains("menu_type` = 'admin'"));
}
@Test
void test_task_159_validate_boundary_single_item() {
for (String key : AdminMenuRouteMatrix.ROUTES.keySet()) {
assertEquals(1, count(sql, key), "column_key 出现一次(WHERE): " + key);
}
}
@Test
void test_task_159_validate_boundary_limit_or_missing_field() {
assertFalse(sql.toLowerCase().contains("insert "), "幂等:只 UPDATE 不 INSERT");
assertFalse(sql.toLowerCase().contains("replace "));
}
@Test
void test_task_159_validate_invalid_input_rejected() {
assertFalse(sql.toLowerCase().contains("delete "));
assertFalse(sql.toLowerCase().contains("drop "));
}
@Test
void test_task_159_validate_dependency_failure_returns_actionable_message() {
// 目标 route 均无前导斜杠(与前端 route 规整后的展示区分)
assertTrue(AdminMenuRouteMatrix.ROUTES.values().stream().noneMatch(v -> v.startsWith("/")));
}
}