Я нашел несколько похожих на этот вопрос вопросов, но их реализации не работают для меня, и мне интересно, если это что-то касается моей тестовой среды или я просто что-то делаю неправильно.
Вот как я прикрепляю файл в моем тестовом запросе:
file := new(bytes.Buffer)
f, err := os.Open("myfile.csv")
if err != nil {
t.Fatal(err)
}
defer f.Close()
io.Copy(f, file)
req, err := http.NewRequest("POST", "/upload", file)
Я получил ошибку: "http: no such file"
Когда я попадаю на строку, в которой file, _, err := r.FormFile("file")
в контроллере.
Мне также было интересно, является ли «file» неправильный ключ для FormFile, поэтому я также попытался «fileupload», и это то же самое. Немного запутался в этом.
Так что я также попытался собрать "csv" на лету с помощью csv.NewWriter, и это дало похожий результат.
Опять же, маршрут отлично работает с запросом почтальона, который примерно одинаков, но по какой-то причине я не могу заставить его работать для моего теста.
Обновление: вот еще тест для ясности того, как я обслуживаю запрос. Благодаря комментарию Флимзи, я удалил io.Copy, и теперь я перешел к новой ошибке:
f, err := os.Open("myfile.csv")
if err != nil {
t.Fatal(err)
}
defer f.Close()
mw := multipart.NewWriter(f)
mw.Close()
req, err := http.NewRequest("POST", "/upload", f)
req.Header.Add("Content-Type", mw.FormDataContentType())
// add the discountID URL var
req = mux.SetURLVars(req, map[string]string{
"discountID": discountID,
})
rr := httptest.NewRecorder()
controller := generateDiscountsController()
// Set middleware memberInfo context
gContext.Set(req, "memberInfo", memberInfo)
// Pass appropriate controller method to http handler in this case
// Get discount
handler := http.HandlerFunc(controller.ImportCSV)
handler.ServeHTTP(rr, req)
resp := response.GetBodyMessage(rr.Body)
assert.Equal(t, 201, rr.Code)
assert.Equal(t, "success", resp)
ошибка: "multipart: NextPart: EOF"
эта ошибка раньше фиксировалась в моем контроллере на err := r.ParseMultipartForm(32 << 20)
В моем контроллере запрос обрабатывается здесь:
func (d *APIDiscount) ImportCSV(w http.ResponseWriter, r *http.Request) {
var buf bytes.Buffer
var firstTen [][]string
var columns []string
defer buf.Reset()
vars := mux.Vars(r)
// using csv writer is safer and better at catching errors than io.Copy
csvData := csv.NewWriter(&buf)
memberInfo := gContext.Get(r, "memberInfo").(*entity.MemberInfo)
err := r.ParseMultipartForm(32 << 20) // max 32 MB <-- Catching here in the test, but not when I send the request through postman on my local server with the same file
if err != nil {
response.InternalError.Send(w, r, memberInfo, 400)
}
file, _, err := r.FormFile("file") // <-- Used to catch here when I used io.Copy
if err != nil {
if err == http.ErrMissingFile {
response.MissingFile.Send(w, r, memberInfo, 400)
return
}
response.FileNotAccepted.Send(w, r, memberInfo, 400)
return
}
// ...