Closed1

gorilla/muxとhttpハンドラテストの相性の悪さ疑惑

さき(H.Saki)さき(H.Saki)

Goでhttpハンドラのテストを書く時には、わざわざサーバーを立てたりせずにhttptest.NewRequesthttptest.NewRecorderを使って擬似的にリクエストを発行することが多いはず。

// handlers.go

// GET /{id}へのリクエストハンドラ
func MyHandler(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r) // gorilla/muxの機能を使ってパスパラメータを取得
	taskId := models.TaskId(params["id"])
	// 以下ハンドラ処理

	fmt.Println("mux.Vars(r): ", params)
	fmt.Println("Id: ", Id)
}
// handler_test.go

// MyHandlerのテスト
func TestMyHandler(t *testing.T) {
	url := fmt.Sprintf("http://localhost:8080/1")
	req := httptest.NewRequest(http.MethodGet, url, nil)
	res := httptest.NewRecorder()

	MyHandler(res, req)

	// 以下resの内容を見てPASS/FAILの判定
}

しかし、テストの中で直接ハンドラ(=MyHandler)を呼んでやると、どうやらパスパラメータの1がmux.Var(r)で取得できていないような挙動を示す。

しかし、mux.NewRouter()で作ったルータをかませる、本番環境用のリクエストの場合は当然パスパラメータの取得は行える。

// main.go

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/{id}", MetricsHandler)

    log.Fatal(http.ListenAndServe("localhost:8080", r))
}

証拠画像

おそらく、mux.Vars()は、muxのルータをかませていないとパラメータが取得できないようになっているのでは。
そうなると、muxを使ったルーティングを前提に処理を書いているハンドラのテストは、httptestを使って直接ハンドラ呼ぶ以外の方法でやる必要があるのでは疑惑。テストとの相性悪くない?
面倒なので何か解決策があればいいのだけど。

公式GitHubのりどみを見ても、パスパラメータつきは普通に別でサーバー立ててそこにリクエスト出す形でやってますね…
テスト関数の中でMyHandlerだけを登録するルーターを作ってました
https://github.com/gorilla/mux#testing-handlers

このスクラップは2022/04/23にクローズされました