Go Echo服务端测试时FormParams无法获取表单值求助
问题解决:Echo框架测试中ctx.FormParams()无法获取表单值
核心问题分析
你的CreateNode接口依赖ctx.FormParams()获取数据,这个方法只负责解析表单类型的请求体(application/x-www-form-urlencoded或multipart/form-data),完全不处理JSON格式的请求,所以你用JSON请求的方式从一开始就走不通。
再看你注释掉的表单请求代码,问题出在Content-Type设置错误:你用url.Values.Encode()生成的是application/x-www-form-urlencoded格式的内容,却把请求头设成了multipart/form-data,导致Echo无法正确解析请求体。
正确的测试方案
根据你的接口实际接收的表单类型,选择对应的测试写法:
方案1:接口接收application/x-www-form-urlencoded表单
这是普通表单的标准格式,修改测试代码如下:
func TestCreateNode(t *testing.T) { expected := "Node created, hooray\n" api := &ServerImplementation{} err := api.Init("host=localhost database=pgx_test user=postgres") if err != nil { t.Fatal(err) } t.Cleanup(func() { t.Log("Cleaning up API") api.Close() }) e := echo.New() // 构造x-www-form-urlencoded格式的表单数据 formVals := make(url.Values) formVals.Set("name", "node1") reqBody := strings.NewReader(formVals.Encode()) // 注意这里的Content-Type要和请求体格式匹配 req := httptest.NewRequest(echo.POST, "/api/nodes", reqBody) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationFormURLEncoded) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) if assert.NoError(t, api.CreateNode(ctx)) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, expected, rec.Body.String()) } }
方案2:接口接收multipart/form-data表单
如果你的接口是处理带文件的多部分表单,需要用multipart.Writer构造请求体:
func TestCreateNode(t *testing.T) { expected := "Node created, hooray\n" api := &ServerImplementation{} err := api.Init("host=localhost database=pgx_test user=postgres") if err != nil { t.Fatal(err) } t.Cleanup(func() { t.Log("Cleaning up API") api.Close() }) e := echo.New() // 创建multipart writer构造请求体 var buf bytes.Buffer writer := multipart.NewWriter(&buf) // 添加表单字段 field, err := writer.CreateFormField("name") if err != nil { t.Fatal(err) } _, _ = field.Write([]byte("node1")) // 如果有文件可以用CreateFormFile // fileField, err := writer.CreateFormFile("file", "test.txt") // ... writer.Close() req := httptest.NewRequest(echo.POST, "/api/nodes", &buf) // 这里要用writer.FormDataContentType()获取正确的Content-Type(包含boundary) req.Header.Set(echo.HeaderContentType, writer.FormDataContentType()) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) if assert.NoError(t, api.CreateNode(ctx)) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, expected, rec.Body.String()) } }
额外说明
关于测试路径:你的实际端点是/api/nodes,测试里之前用/虽然直接调用方法不会影响路由匹配,但建议保持路径一致,避免后续测试出现其他问题。
内容的提问来源于stack exchange,提问作者Drew
相关产品推荐
相关产品推荐

