eac0137069
Closes part of HIF-4 (Stage 2 前端集成反馈 F9 - 全站响应格式)
F9 (P1): 全站响应统一 {code, msg, data} 三字段固定 shape
- ResponseSuccessBean.Data 去掉 omitempty → 空 payload 也返 "data":null
- ResponseErrorBean 加 Data interface{} 字段 → 错误响应也带 "data":null
- App 端强类型 decoder 依赖固定字段 shape,缺 data 键会解码失败
回归护栏 3 用例:
- TestResponseErrorBean_HasDataField: 错误响应必须含 "data":null
- TestResponseSuccessBean_DataAlwaysPresent: Success(nil) 也含 "data":null(防 omitempty 回退)
- TestResponseSuccessBean_WithPayload: 正常 payload 序列化正确
影响面:全站所有响应(不止 lottery),JSON 加字段/字段值变 null 对现有 client 无 breaking(宽松 decoder 全兼容)
CI 全绿;单 file 改动 revert 一步搞定
55 lines
2.0 KiB
Go
55 lines
2.0 KiB
Go
// responseBean_test.go — HIF-4 F9 护栏:
|
||
// 所有 HTTP 响应必须是 {code, msg, data} 三字段固定 shape,data 为空时也要
|
||
// 显式 "null"(不是丢字段)。App 端强类型 decoder 依赖这个 shape。
|
||
package result
|
||
|
||
import (
|
||
"encoding/json"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// TestResponseErrorBean_HasDataField 断言错误响应的 JSON 一定包含 data 字段
|
||
// 且为 null。如果未来有人给 Data 加了 omitempty,或者删掉 Data 字段,这里会挂。
|
||
func TestResponseErrorBean_HasDataField(t *testing.T) {
|
||
body, err := json.Marshal(Error(40003, "User token is invalid"))
|
||
if err != nil {
|
||
t.Fatalf("marshal: %v", err)
|
||
}
|
||
s := string(body)
|
||
if !strings.Contains(s, `"data":null`) {
|
||
t.Fatalf("F9 regression: error response missing 'data:null', got %s", s)
|
||
}
|
||
// 顺带断言 code + msg 也在(防止未来无脑重构删字段)
|
||
if !strings.Contains(s, `"code":40003`) || !strings.Contains(s, `"msg":"User token is invalid"`) {
|
||
t.Fatalf("error response missing code/msg, got %s", s)
|
||
}
|
||
}
|
||
|
||
// TestResponseSuccessBean_DataAlwaysPresent 断言成功响应在 data 为 nil 时
|
||
// 也显式返回 "data":null(不是丢字段)。这是 F9 的另一半——如果有人未来把
|
||
// omitempty 加回去,只解决错误响应的对称性会被打破。
|
||
func TestResponseSuccessBean_DataAlwaysPresent(t *testing.T) {
|
||
body, err := json.Marshal(Success(nil))
|
||
if err != nil {
|
||
t.Fatalf("marshal: %v", err)
|
||
}
|
||
s := string(body)
|
||
if !strings.Contains(s, `"data":null`) {
|
||
t.Fatalf("F9 regression: Success(nil) missing 'data:null' (omitempty regression?), got %s", s)
|
||
}
|
||
}
|
||
|
||
// TestResponseSuccessBean_WithPayload 副断言:非 nil payload 时
|
||
// data 字段确实带上,且序列化正常。
|
||
func TestResponseSuccessBean_WithPayload(t *testing.T) {
|
||
body, err := json.Marshal(Success(map[string]any{"id": 42, "name": "abc"}))
|
||
if err != nil {
|
||
t.Fatalf("marshal: %v", err)
|
||
}
|
||
s := string(body)
|
||
if !strings.Contains(s, `"data":{`) || !strings.Contains(s, `"id":42`) {
|
||
t.Fatalf("success payload not serialized correctly, got %s", s)
|
||
}
|
||
}
|