Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Unable to see the vars when calling from a unit test #373

Closed
swalberg opened this issue May 12, 2018 · 6 comments
Closed

Unable to see the vars when calling from a unit test #373

swalberg opened this issue May 12, 2018 · 6 comments

Comments

@swalberg
Copy link
Contributor

What version of Go are you running? go version go1.10.2 darwin/amd64

What version of gorilla/mux are you at? 5e55a4a

Describe your problem (and what you have tried so far)

I'm trying to test a route with a path variable but the handler sees an empty map when called from a unit test. It works fine with cURL against a running instance.

Paste a minimal, runnable, reproduction of your issue below (use backticks to format it)
I have slightly altered the example from the README.

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

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

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

func MetricsHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")

	vars := mux.Vars(r)
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "Type: %v", vars["type"])
}
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestMetricsHandler(t *testing.T) {
	tt := []struct {
		routeVariable string
		shouldPass    bool
	}{
		{"goroutines", true},
		{"heap", true},
		{"counters", true},
		{"queries", true},
		{"adhadaeqm3k", false},
	}

	for _, tc := range tt {
		path := fmt.Sprintf("/metrics/%s", tc.routeVariable)
		req, err := http.NewRequest("GET", path, nil)
		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		handler := http.HandlerFunc(MetricsHandler)
		handler.ServeHTTP(rr, req)

		expected := fmt.Sprintf("Type: %v", tc.routeVariable)

		if rr.Body.String() != expected {
			t.Errorf("handler should have failed on routeVariable %s: got %v want %v",
				tc.routeVariable, rr.Body.String(), expected)
		}
	}
}
sean~/go/src/gitlab.com/swalberg/muxtest$ go test *
--- FAIL: TestMetricsHandler (0.00s)
	endpoints_test.go:36: handler should have failed on routeVariable goroutines: got Type:  want Type: goroutines
	endpoints_test.go:36: handler should have failed on routeVariable heap: got Type:  want Type: heap
	endpoints_test.go:36: handler should have failed on routeVariable counters: got Type:  want Type: counters
	endpoints_test.go:36: handler should have failed on routeVariable queries: got Type:  want Type: queries
	endpoints_test.go:36: handler should have failed on routeVariable adhadaeqm3k: got Type:  want Type: adhadaeqm3k
FAIL
FAIL	command-line-arguments	0.014s
@swalberg
Copy link
Contributor Author

Been trying this out with a few different versions of gorilla/mux as far back as 94903de and none of them work with this. Am I doing something incorrectly? Possibly a dupe of #342?

@swalberg
Copy link
Contributor Author

I changed my tests to set the vars directly like in #342 and it passes:

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestMetricsHandler(t *testing.T) {
	tt := []struct {
		routeVariable string
		shouldPass    bool
	}{
		{"goroutines", true},
		{"heap", true},
		{"counters", true},
		{"queries", true},
		{"adhadaeqm3k", false},
	}

	for _, tc := range tt {
		path := "whocares"
		req, err := http.NewRequest("GET", path, nil)
		if err != nil {
			t.Fatal(err)
		}
		req = mux.SetURLVars(req, map[string]string{
			"type": tc.routeVariable,
		})
		rr := httptest.NewRecorder()
		/* Appears we can call it directly if we want?
			handler := http.HandlerFunc(MetricsHandler)
			handler.ServeHTTP(rr, req)*/
		MetricsHandler(rr, req)

		expected := fmt.Sprintf("Type: %v", tc.routeVariable)

		if rr.Body.String() != expected {
			t.Errorf("handler should have failed on routeVariable %s: got %v want %v",
				tc.routeVariable, rr.Body.String(), expected)
		}
	}
}

Can you elaborate on comments in #342? My understanding is "yes you can use mux.SetURLVars but you should really do it the way I've shown" which I prefer, but can't get to work.

Thanks!

@kisielk
Copy link
Contributor

kisielk commented May 12, 2018 via email

@elithrar
Copy link
Contributor

elithrar commented May 12, 2018 via email

swalberg added a commit to swalberg/mux that referenced this issue May 13, 2018
The example in the README does not pass the request through a mux therefore the request variables from the path are never populated. Update the sample to create a minimum viable router to use.

Fixes gorilla#373
@swalberg
Copy link
Contributor Author

OK, thanks @elithrar and @kisielk, that was enough to get me to something working. I've made a PR to fix the docs to reflect our discussion. If that's still not the right way please let me know and I'll be happy to fix!

Sean

elithrar pushed a commit that referenced this issue May 13, 2018
The example in the README does not pass the request through a mux therefore the request variables from the path are never populated. Update the sample to create a minimum viable router to use.

Fixes #373
@Guilhermeslucas
Copy link

@swalberg Thanks a lot for your response, man. Your help fixed the problem I was having the whole afternoon. Thanks a lot!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants