想在Golang的单元测试中添加一个FormFile

4

我想测试带有json主体和测试文件的httpRequest。除了主体json之外,我不知道如何将创建的测试文件添加到请求中。

body := strings.NewReader(URLTest.RequestBody)
        request, err := http.NewRequest(URLTest.MethodType, "localhost:"+string(listeningPort)+URLTest.URL, body)
        if err != nil {
            t.Fatalf("HTTP NOT WORKING")
        }

        fileBuffer := new(bytes.Buffer)
        mpWriter := multipart.NewWriter(fileBuffer)
        fileWriter, err := mpWriter.CreateFormFile("file", "testfile.pdf")
        if err != nil {
            t.Fatalf(err.Error())
        }
        file, err := os.Open("testfile.pdf")
        if err != nil {
            t.Fatalf(err.Error())
        }
        defer file.Close()
        _, err = io.Copy(fileWriter, file)
        if err != nil {
            t.Fatalf(err.Error())
        }

        rec := httptest.NewRecorder()
        UploadFiles(rec, request, nil)
        response := rec.Result()
        if response.StatusCode != URLTest.ExpectedStatusCode {
            t.Errorf(URLTest.URL + " status mismatch")
        }

        responseBody, err := ioutil.ReadAll(response.Body)
        defer response.Body.Close()

        if err != nil {
            t.Errorf(URLTest.URL + " cant read response")
        } else {
            if strings.TrimSpace(string(responseBody)) != URLTest.ExpectedResponseBody {
                t.Errorf(URLTest.URL + " response mismatch - have: " + string(responseBody) + " want: " + URLTest.ExpectedResponseBody)
            }
        }
    }

我可以像这样添加文件值吗:request.FormFile.Add(...)或者其他什么吗?

你好,欢迎来到StackOverflow!请阅读如何创建良好的代码示例以帮助我们帮助您!您应该包含最少量的代码来完全说明您的问题。理想情况下,我们可以只复制粘贴您的代码并运行它以重新创建错误。 - Oliver Baumann
1个回答

2

关于如何在Go中使用HTTP请求发送文件的问题,以下是一些示例代码。

您需要使用mime/multipart来构建表单。

package main

import (
    "bytes"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "net/http/httptest"
    "net/http/httputil"
    "os"
    "strings"
)

func main() {

    var client *http.Client
    var remoteURL string
    {
        //setup a mocked http client.
        ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            b, err := httputil.DumpRequest(r, true)
            if err != nil {
                panic(err)
            }
            fmt.Printf("%s", b)
        }))
        defer ts.Close()
        client = ts.Client()
        remoteURL = ts.URL
    }

    //prepare the reader instances to encode
    values := map[string]io.Reader{
        "file":  mustOpen("main.go"), // lets assume its this file
        "other": strings.NewReader("hello world!"),
    }
    err := Upload(client, remoteURL, values)
    if err != nil {
        panic(err)
    }
}

func Upload(client *http.Client, url string, values map[string]io.Reader) (err error) {
    // Prepare a form that you will submit to that URL.
    var b bytes.Buffer
    w := multipart.NewWriter(&b)
    for key, r := range values {
        var fw io.Writer
        if x, ok := r.(io.Closer); ok {
            defer x.Close()
        }
        // Add an image file
        if x, ok := r.(*os.File); ok {
            if fw, err = w.CreateFormFile(key, x.Name()); err != nil {
                return
            }
        } else {
            // Add other fields
            if fw, err = w.CreateFormField(key); err != nil {
                return
            }
        }
        if _, err = io.Copy(fw, r); err != nil {
            return err
        }

    }
    // Don't forget to close the multipart writer.
    // If you don't close it, your request will be missing the terminating boundary.
    w.Close()

    // Now that you have a form, you can submit it to your handler.
    req, err := http.NewRequest("POST", url, &b)
    if err != nil {
        return
    }
    // Don't forget to set the content type, this will contain the boundary.
    req.Header.Set("Content-Type", w.FormDataContentType())

    // Submit the request
    res, err := client.Do(req)
    if err != nil {
        return
    }

    // Check the response
    if res.StatusCode != http.StatusOK {
        err = fmt.Errorf("bad status: %s", res.Status)
    }
    return
}

希望您可以在单元测试中使用这个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接