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するファイルとして準備