formsgotestinghttp.client

Create a broken form with http.Client


How to create a 'broken' form for testing purposes with http.Client that will trigger a response error on ParseForm() in a handler function?

I have the following code:

func (app *App) signupUser(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil { // how to trigger this if statement?
        sendStatus(w, http.StatusBadRequest, "error parsing form")
        return
    }
...

Then during testing I'm using http.Client to test this controller:

resp, err = client.PostForm(ts.URL+"/user/signup", url.Values{
            "email":      {testEmail},
            "password":   {goodPassword},
)
if err != nil { 
  t.Error(err) // I never get here
}

Solution

  • First of all client.PostForm will do a proper job of populating the post form, so you have to populate it manually.

    Then if you dig into the call stack of r.ParseForm(), you'll eventually arrive to the error producers (barring reading issues, etc.):

    "net/url".QueryUnescape which "returns an error if any % is not followed by two hexadecimal digits."

    So, for example:

        r := &http.Request{
            // ensures it reads the body
            Method: "POST", 
            // string with bad url encoding '%3z'
            Body: io.NopCloser(strings.NewReader("foo%3z1%26bar%3D2")),
            // ensures it parses the body as post form
            Header: map[string][]string{
                "Content-Type": []string{
                    "application/x-www-form-urlencoded",
                },
            },
        }
        err := r.ParseForm()
        if err == nil {
            panic("no err")
        }
        // err -> invalid URL escape "%3z"