I am new to Go. I wrote an API server built on top of the Echo server using the DeepMap OpenAPI generator and Postgres using pgxpool. It works fine and is a year old, but that doesn't mean it's written correctly :).
The test server has been using a shell script and a series of Curl calls, which works great, but I'm trying to update the tests to use Go's testing framework. I've done some basic testing, but anything that requires form values doesn't work - the handler function doesn't see any form values, so I'm guessing the request isn't encapsulating them, but I don't understand why.
The following is the first part of the CreateNode()
method, which implements part of the generated API interface. I've omitted the body; the failing part is what appears in context.
func (si *ServerImplementation) CreateNode(ctx echo.Context) error { vals, err := ctx.FormParams() info("In CreateNode() with FormParams %v", vals) ...
This is the test function:
func TestCreateNode(t *testing.T) { // not the actual expected return expected := "Node created, hooray\n" // initialize database with current schema api := &ServerImplementation{} err := api.Init("host=localhost database=pgx_test user=postgres") if err != nil { t.Fatal(err) } // handle teardown in this deferred function t.Cleanup(func() { t.Log("Cleaning up API") api.Close() }) // start up webserver e := echo.New() // this didn't work either //f := make(url.Values) //f.Set("name", "node1") //req := httptest.NewRequest(http.MethodPost, "/nodes/", strings.NewReader(f.Encode())) //req.Header.Add("Content-Type", "multipart/form-data") req := httptest.NewRequest(echo.POST, "/", strings.NewReader(`{"name":"node1"}`)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) 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()) } }
I won't bother with the full test output, because when CreateNode()
receives no value, everything fails:
=== RUN TestCreateNode 2023/08/26 15:09:43 INFO: In CreateNode() with FormParams map[] 2023/08/26 15:09:43 INFO: No name provided in CreateNode()
As far as I know, I'm following similar examples closely. I hope this is enough detail, but don't want to overload the issue with unnecessary support code.
The endpoint for nodes is /nodes
and the base URL for the API is /api
, but neither of those are reflected here, from the examples I've seen of them is unnecessary. Echo's examples always use /
as endpoints.
Okay, I am Ding Dong.
I've cobbled together a lot of examples trying to get something to work, and only once did I try the following in a test function:
req.Header.Set("Testing", "Yes")
and pop it in CreateNode
:
info("Header: %v", ctx.Request().Header)
This gives me:
2023/08/26 20:04:36 INFO: Header: map[Content-Type:[application/x-www-form-urlencoded] Testing:[Yes]]
I see that the request is going well, it has to do with the way I formed the request.
I checked the examples again and realized that I was setting the form value based on one example but setting the content type from another example. The works are as follows:
f := make(url.Values) f.Set("name", "node1") req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode())) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
Of course, doing this via JSON won't work because that's not how CreateNode() parses the incoming information.
This is just my carelessness!
The above is the detailed content of Form variables are not available in tests. For more information, please follow other related articles on the PHP Chinese website!