如何在尝试测试端点时设置Request.FormFile?
部分代码:
func (a *EP) Endpoint(w http.ResponseWriter, r *http.Request) {
...
x, err := strconv.Atoi(r.FormValue("x"))
if err != nil {
a.ren.Text(w, http.StatusInternalServerError, err.Error())
return
}
f, fh, err := r.FormFile("y")
if err != nil {
a.ren.Text(w, http.StatusInternalServerError, err.Error())
return
}
defer f.Close()
...
}如何使用httptest lib生成具有可以在FormFile中获取的值的post请求?
发布于 2019-07-18 05:21:02
您不需要按照另一个答案的建议模拟完整的FormFile结构。mime/multipart包实现了一个允许您创建FormFile的写入器类型。来自the docs
CreateFormFile是CreatePart的便捷包装器。它使用提供的字段名和文件名创建一个新的表单数据标题。
func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error)然后,您可以将此io.Writer传递给httptest.NewRequest,它接受一个读取器作为参数。
request := httptest.NewRequest("POST", "/", myReader)为此,您可以将FormFile写入io.ReaderWriter缓冲区或使用io.Pipe。下面是一个使用管道的完整示例:
func TestUploadImage(t *testing.T) {
//Set up a pipe to avoid buffering
pr, pw := io.Pipe()
//This writers is going to transform
//what we pass to it to multipart form data
//and write it to our io.Pipe
writer := multipart.NewWriter(pw)
go func() {
defer writer.Close()
//we create the form data field 'fileupload'
//wich returns another writer to write the actual file
part, err := writer.CreateFormFile("fileupload", "someimg.png")
if err != nil {
t.Error(err)
}
//https://yourbasic.org/golang/create-image/
img := createImage()
//Encode() takes an io.Writer.
//We pass the multipart field
//'fileupload' that we defined
//earlier which, in turn, writes
//to our io.Pipe
err = png.Encode(part, img)
if err != nil {
t.Error(err)
}
}()
//We read from the pipe which receives data
//from the multipart writer, which, in turn,
//receives data from png.Encode().
//We have 3 chained writers !
request := httptest.NewRequest("POST", "/", pr)
request.Header.Add("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
handler := UploadFileHandler()
handler.ServeHTTP(response, request)
t.Log("It should respond with an HTTP status code of 200")
if response.Code != 200 {
t.Errorf("Expected %s, received %d", 200, response.Code)
}
t.Log("It should create a file named 'someimg.png' in uploads folder")
if _, err := os.Stat("./uploads/someimg.png"); os.IsNotExist(err) {
t.Error("Expected file ./uploads/someimg.png' to exist")
}
}此函数利用image包动态生成一个文件,利用您可以将io.Writer传递给png.Encode这一事实。同样地,你可以通过你的多部分写入器来生成CSV格式的字节(在包“NewWriter/csv”中的编码),动态地生成一个文件,而不需要从你的文件系统中读取任何东西。
发布于 2017-05-11 10:40:37
如果您查看了FormFile函数的实现,就会看到它读取了公开的MultipartForm字段。
https://golang.org/src/net/http/request.go?s=39022:39107#L1249
// FormFile returns the first file for the provided form key.
1258 // FormFile calls ParseMultipartForm and ParseForm if necessary.
1259 func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
1260 if r.MultipartForm == multipartByReader {
1261 return nil, nil, errors.New("http: multipart handled by MultipartReader")
1262 }
1263 if r.MultipartForm == nil {
1264 err := r.ParseMultipartForm(defaultMaxMemory)
1265 if err != nil {
1266 return nil, nil, err
1267 }
1268 }
1269 if r.MultipartForm != nil && r.MultipartForm.File != nil {
1270 if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
1271 f, err := fhs[0].Open()
1272 return f, fhs[0], err
1273 }
1274 }
1275 return nil, nil, ErrMissingFile
1276 }在测试中,您应该能够创建multipart.Form的测试实例并将其分配给请求对象-- https://golang.org/pkg/mime/multipart/#Form
type Form struct {
Value map[string][]string
File map[string][]*FileHeader
}当然,这将要求您使用真正的文件路径,这从测试的角度来看并不是很好。要解决这个问题,可以定义一个接口来从请求对象中读取FormFile,并将模拟实现传递到EP结构中。
这里有一个很好的帖子,里面有几个关于如何做到这一点的例子:https://husobee.github.io/golang/testing/unit-test/2015/06/08/golang-unit-testing.html
发布于 2020-07-27 20:20:05
我将这些答案和其他答案组合到一个没有管道或goroutines的Echo示例中:
func Test_submitFile(t *testing.T) {
path := "testfile.txt"
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("object", path)
assert.NoError(t, err)
sample, err := os.Open(path)
assert.NoError(t, err)
_, err = io.Copy(part, sample)
assert.NoError(t, err)
assert.NoError(t, writer.Close())
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/", body)
req.Header.Set(echo.HeaderContentType, writer.FormDataContentType())
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
c.SetPath("/submit")
if assert.NoError(t, submitFile(c)) {
assert.Equal(t, 200, rec.Code)
assert.Contains(t, rec.Body.String(), path)
fi, err := os.Stat(expectedPath)
if os.IsNotExist(err) {
t.Fatal("Upload file does not exist", expectedPath)
}
assert.Equal(t, wantSize, fi.Size())
}
}https://stackoverflow.com/questions/43904974
复制相似问题