Go测试出现Request validation failed错误,正常运行无异常
问题:Golang测试时触发请求体格式验证错误,正常运行无异常
正常运行代码时无任何错误,但执行测试用例调用相同函数时,触发了"Request validation failed"错误,错误详情显示请求体应为object类型。测试使用的JSON文件与正常运行时完全一致,请问该问题可能的原因是什么?需要检查代码的哪些部分来修复测试?
错误信息
{"error":"Request validation failed","validation":[{"keyword":"type","dataPath":".body","schemaPath":"#/properties/body/type","params":{"type":"object"},"message":"should be object"}]}
测试函数
func TestSync(t *testing.T) { var url_base string = "http://localhost:8080" var token string = "xxx" fileJson := EnvVars("test3_0.json") Sync(url_base, token, fileJson) responseServer := StatusFeaturesServer(url_base+"/api/admin/projects/default", token) expected, _ := json.Marshal(fileJson) server, _ := json.Marshal(responseServer) if !cmp.Equal(responseServer, fileJson) { t.Errorf("Expected '%s', but got '%s'", string(expected), string(server)) } }
业务代码
// JSON结构定义 type Features struct { Name string `json:"name"` Enabled bool `json:"enabled"` } type Environment struct { Environment string `json:"environment"` Features []Features `json:"features"` } type Environments struct { Environments []Environment `json:"environments"` } func EnvVars(file_json string) *Environments { // 打开JSON文件 jsonFile, err := os.Open(file_json) if err != nil { fmt.Println(err) } // 延迟关闭文件 defer jsonFile.Close() // 读取文件内容为字节数组 byteValue, errioutil := io.ReadAll(jsonFile) if errioutil != nil { fmt.Println(errioutil) } // 初始化结构体 var dataJson Environments // 将字节数组反序列化为结构体 errjson := json.Unmarshal([]byte(byteValue), &dataJson) if errjson != nil { fmt.Println(errjson) } fmt.Println("Successfully processed json file") return &dataJson } func Sync(url_base string, token string, fileJson *Environments) { for _, e := range fileJson.Environments { for _, f := range e.Features { FFSync(url_base, token, f.Name, e.Environment, strconv.FormatBool(f.Enabled)) } } } func FFSync(url_base string, token string, feature string, environment string, enabled string) { url := fmt.Sprintf(url_base+"/api/admin/projects/default/features/%s/environments/%s/%s", feature, environment, enabled) ApiCall(token, nil, url) } func ApiCall(token string, data interface{}, url string) { payloadBytes, err := json.Marshal(data) if err != nil { log.Fatal(err) } body := bytes.NewReader(payloadBytes) client := &http.Client{} req, err := http.NewRequest("POST", url, body) if err != nil { log.Fatal(err) } req.Header.Set("Authorization", token) req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() bodyText, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", string(bodyText)) }
问题原因及修复方案
核心原因
测试和正常运行的差异点在于请求体内容:在FFSync函数中,调用ApiCall时传入的data参数是nil。当json.Marshal(nil)时会生成null的JSON内容,但后端接口明确要求请求体是object类型,因此触发验证错误。
正常运行时无报错,大概率是生产场景下调用ApiCall时传入的不是nil,或者后端对null的处理更宽松,而测试环境的验证规则更严格。
需要检查和修复的代码部分
修正
FFSync的请求体构造
后端要求请求体为object类型,不能传入nil,需要构造符合接口要求的结构体作为请求体。同时注意原代码中把enabled作为路径参数的设计可能不符合POST接口的常规传参方式,需确认接口文档调整:// 定义接口要求的请求体结构体 type FeatureUpdateReq struct { Enabled bool `json:"enabled"` } func FFSync(url_base string, token string, feature string, environment string, enabled string) { // 调整URL,移除路径中的enabled参数 url := fmt.Sprintf(url_base+"/api/admin/projects/default/features/%s/environments/%s", feature, environment) enabledBool, _ := strconv.ParseBool(enabled) // 构造符合要求的请求体数据 reqData := FeatureUpdateReq{Enabled: enabledBool} ApiCall(token, reqData, url) }给
ApiCall添加空数据处理逻辑
如果存在确实需要传空请求体的场景,避免生成null,改为传入空对象{}:func ApiCall(token string, data interface{}, url string) { var body *bytes.Reader if data != nil { payloadBytes, err := json.Marshal(data) if err != nil { log.Fatal(err) } body = bytes.NewReader(payloadBytes) } else { // 传入空对象而非null,满足接口的object类型要求 body = bytes.NewReader([]byte("{}")) } client := &http.Client{} req, err := http.NewRequest("POST", url, body) // 后续代码保持不变 }校验测试环境的后端规则
确认测试环境的后端接口schema是否与生产环境一致,是否测试环境启用了更严格的验证规则,导致null请求体被拦截。
内容的提问来源于stack exchange,提问作者X T
相关产品推荐
相关产品推荐

