package gateway import ( "strings" "testing" "github.com/swaggo/swag" _ "yunyan/swagger" // 与 wservice_comp.go 同样的空导入:注册 SwaggerInfo ) // gateway 用 /swagger/*any 对外提供 API 文档,文档本体是一份 text/template, // 由 swag.ReadDoc() 在运行时用 SwaggerInfo 渲染。 // // 坑在于:**模板解析/执行失败时 swag 不报错,而是原样返回未渲染的模板** // (见 swag.Spec.ReadDoc)。于是 /swagger/doc.json 里 host 就是字面量 "{{.Host}}", // swagger UI 拼出 "https://{{.Host}}{{.BasePath}}/api/..." 这种非法地址, // 页面上点任何接口都是 "Failed to fetch"——**所有接口一起坏**, // 从现象很难联想到是某条注释把模板写崩了。 // // 触发条件极易踩:任何 proto/handler 注释里出现 "{{"(例如写变量占位符), // 都会被 swag 生成进 description,进而让整份模板解析失败。 // // 本测试放在 gateway 而不是 swagger/ 目录:swagger/ 是生成物目录, // 镜像构建时会重跑 swag init 覆盖 docs.go,其包名取决于生成命令 // (Dockerfile 不带 --packageName,生成 package swagger;仓库里现存的是 swg2), // 测试文件放进去会和重新生成的包名打架,直接把镜像构建搞挂。 func TestSwaggerDocRenders(t *testing.T) { doc, err := swag.ReadDoc() if err != nil { t.Fatalf("swag.ReadDoc 失败: %v", err) } for _, leftover := range []string{"{{.Host}}", "{{.BasePath}}", "{{ marshal", "{{escape"} { if strings.Contains(doc, leftover) { t.Fatalf("swagger 模板未渲染,doc.json 里残留 %q。\n"+ "多半是某条接口/字段注释里写了 \"{{\",把 text/template 解析打断了——"+ "搜 swagger/docs.go 里的 \"{{\",把注释改成不带双大括号的写法后重跑 swag init。", leftover) } } if !strings.Contains(doc, "\"swagger\": \"2.0\"") { t.Fatal("渲染结果不像 swagger 文档,检查 swagger/docs.go 是否被破坏") } }