Skip to content
New issue

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

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

Already on GitHub? Sign in 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!

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

No branches or pull requests

4 participants