🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

Q&A

解決済

2回答

3770閲覧

Ginフレームワークのテスト c.PostFormで受け取るデータを送りたい

shunyaYoshimra

総合スコア7

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

0グッド

0クリップ

投稿2021/02/17 06:58

前提・実現したいこと

GolangのGinフレームワークのテストを書いているのですが、テストで送ったデータをC.PostFormで受け取ることができません。解決策が分かる方、ご教示下さると助かります。

###現状
下記のコードだと、controllerのSignup関数の中にある、
C.PostForm("email")
c.PostForm("name")
c.PostForm("password")
で、送ったデータを取得することができませんでした。
”全ての情報を入力してください(All information should be filled in.)”という、Signup関数内のエラーが返って来るので、ルーターなどの問題ではないと思います。

該当のソースコード

test

1func InitTestUserCreate(body map[string]interface{}) *httptest.ResponseRecorder { 2 r := gin.Default() 3 app := new(apps.Application) 4 app.CreateTest(r) 5 6 w := httptest.NewRecorder() 7 b, _ := json.Marshal(body) 8 req, _ := http.NewRequest(http.MethodPost, "/api/test/signup", strings.NewReader(string(b))) 9 req.Header.Set("Content-Type", "application/json") 10 r.ServeHTTP(w, req) 11 return w 12} 13 14func TestUserCreate(t *testing.T) { 15 t.Run("it should return success", func(t *testing.T) { 16 defer database.DropAllTable() 17 body := map[string]interface{}{ 18 "name": "User Test", 19 "email": "user@email.com", 20 "password": "password", 21 } 22 w := InitTestUserCreate(body) 23 t.Log(w) 24 assert.Equal(t, http.StatusOK, w.Code) 25 }) 26}

controller

1func (uc *UserController) Signup(c *gin.Context) { 2 var user entity.User 3 email := c.PostForm("email") 4 name := c.PostForm("name") 5 pass := c.PostForm("password") 6// ↑ここで、テストから送られたデータを受け取りたい... 7 if name == "" || email == "" || pass == "" { 8 res := response.BadRequest("全ての情報を入力してください(All information should be filled in.)") 9 c.JSON(res.Status, res) 10 } else { 11 if _, err := uc.Repository.FindByEmail(email); err == nil { 12 res := response.Conflict("このメールアドレスは既に登録されています(This e-mail has already been registered)") 13 c.JSON(res.Status, res) 14 } else { 15 passwordEncrypt, _ := middleware.PasswordEncrypt(pass) 16 user = entity.User{ 17 Name: name, 18 Email: email, 19 Password: passwordEncrypt, 20 } 21 if err := uc.Repository.Create(&user); err != nil { 22 res := response.BadRequest("予期せぬエラーが発生しました(An unexpected error has occured)") 23 c.JSON(res.Status, res) 24 } else { 25 userID := user.ID 26 middleware.Login(c, userID) 27 res := response.SuccessResponse("") 28 c.JSON(res.Status, res) 29 } 30 } 31 } 32} 33

質問に不備があれば、再掲させていただきます。
ご回答の程、宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

GinでJSON形式(application/json)エンコードによるリクエストを解釈するには

c.ShouldBindJSON(&v)

とすべきだと思います。

「c.PostForm」で解釈できるのはリクエストのエンコードが以下のどちらかだと思います。

  • multipart/form-data
  • application/x-www-form-urlencoded

投稿2021/02/17 23:55

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shunyaYoshimra

2021/02/18 03:15

早速のご回答有難うございます。 c.ShouldBindJSON(&v)のメソッドで値を取得することができました。有難うございます。 ただ、c.SholdBindJSONを使うと、回答者様のご指摘の通り、今度はフロントエンドのフォームからのデータ(multipart/form-data application/x-www-form-urlencoded)を受け取れなくなってしまいます。 テストと、実際のフォームの両方から同じ関数内でデータを受け取る事はできるのでしょうか? またしても初歩的あるいは、的を射ていない質問かもしれませんが、答えられる範囲でいいので、教えて下さると嬉しいです。
nobonobo

2021/02/18 04:14

フロントエンドも同様にapplication/jsonでPOSTするようにしてみるのも解決の一つですが、 テストコードの方ををmultipart/form-dataかapplication/x-www-form-urlencoded変えるべきですね。
shunyaYoshimra

2021/02/18 04:49

テストコードをapplication/x-www-form-urlencodedに変更して、無事ユニットテストが通りました。丁寧に教えて下さり有難うございました。
guest

0

解決後のコードです。

test

1func InitTestUserCreate(name, email, pass string) *httptest.ResponseRecorder { 2 r := gin.Default() 3 app := new(apps.Application) 4 app.CreateTest(r) 5 6 form := url.Values{} 7 form.Add("name", name) 8 form.Add("email", email) 9 form.Add("password", pass) 10 body := strings.NewReader(form.Encode()) 11 12 w := httptest.NewRecorder() 13 req, _ := http.NewRequest(http.MethodPost, "/api/test/signup", body) 14 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 15 r.ServeHTTP(w, req) 16 return w 17}

投稿2021/02/18 05:06

shunyaYoshimra

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問