You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的处理更宽松,而测试环境的验证规则更严格。

需要检查和修复的代码部分

  1. 修正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)
    }
    
  2. 给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)
        // 后续代码保持不变
    }
    
  3. 校验测试环境的后端规则
    确认测试环境的后端接口schema是否与生产环境一致,是否测试环境启用了更严格的验证规则,导致null请求体被拦截。


内容的提问来源于stack exchange,提问作者X T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:01:06