multipart/form-dataのテストを行いたい(featureテストのような)
ここのサイトがとても参考になりました
stackoverflow.com
HTML
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>{{ .Title }}</title> </head> <body> <form action="/file/upload_request" enctype="multipart/form-data" method="post"> <input type="file" name="up_data" id="upload" multiple="multiple"> <input type="submit" value="Upload file" /> </form> </body> </html>
このようなHTMLを使うとします。
up_data
がPOSTするファイル。
golangのソース
実際のコントローラはこのような感じ
func UploadFileRequest(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { w.WriteHeader(http.StatusBadRequest) return } file, fileHeader, err := r.FormFile("up_data") defer file.Close() if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, "file is needed") return } buf := bytes.NewBuffer(nil) if _, err := io.Copy(buf, file); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, "save file failed.") return } fmt.Fprintf(w, "file: %v", fileHeader) // ファイルを保存するような処理(usecaseを使ったり) }
これのテストを行いたい
テストコード
func TestFileHTMLHandler(t *testing.T) { t.Run("UploadFile正常系", func(t *testing.T) { var b bytes.Buffer // multipartのリクエスト用オブジェクト w := multipart.NewWriter(&b) // ハンドラの準備(テスト用リクエスト) spy := &fakeFileUseCase{ FakeCreate: func(files.File) (*files.File, error) { return nil, nil }, } ts := httptest.NewServer(http.HandlerFunc(UploadFileRequest)) defer ts.Close() client := ts.Client() var fw io.Writer f, err := os.Open("main.go") if err != nil { fmt.Errorf("err should be nil: %v", err) } w.CreateFormFile("up_data", "main.go") written, err := io.Copy(fw, f) if written == 0 { fmt.Errorf("written should be a positive value: %v", err) } w.Close() req, err := http.NewRequest("POST", ts.URL, &b) if err != nil { fmt.Errorf("err should be nil: %v", err) } // 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 { fmt.Errorf("err should be nil: %v", err) } // Check the response if res.StatusCode != http.StatusOK { fmt.Errorf("bad status: %s", res.Status) } }) }
補足
ts := httptest.NewServer
を使ってテスト用のサーバを準備http.NewRequest("POST", ts.URL, &b)
でPOSTのテスト(URLはhttptest.NewServer
によって準備されたテキトーなURL)w.CreateFormFile("up_data", "main.go")
により、up_data
という名前でmain.go
をPOSTするファイルとして準備