1

I've been trying for sometime to figure out how a write unit tests for handlers that use context as part of their definition.

Example

func Handler(ctx context.Context, w http.ResponseWriter, r *http.Request)

After some googling I came accross this article which made it seem as simple as

//copied right from the article

rr := httptest.NewRecorder()
// e.g. func GetUsersHandler(ctx context.Context, w http.ResponseWriter, r *http.Request)
handler := http.HandlerFunc(GetUsersHandler)

When trying to to implement the tests like this I was given the error

cannot convert Handler (type func("context".Context, http.ResponseWriter, *http.Request)) to type http.HandlerFunc

So I drove into the definition of HandleFunc and found

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

So the error makes sense... but now I'm at a lose because I need to test this Handler and it doesn't seem like I can using httptest as the article suggested.

Is there anyway to test my handlers with the httptest package? If not how should I go about testing?

I'm using Go1.9

UPDATE

//Just so its clear this is what I'm currently trying to do

data := url.Values{}
data.Set("event_type", "click")
data.Set("id", "1")
data.Set("email", "")

req, err := http.NewRequest("PUT", "/", bytes.NewBufferString(data.Encode()))
Expect(err).To(BeNil())

rr := httptest.NewRecorder()
// this is the problem line. 
// The definition of Handler isn't (w ResponseWriter, r *Request)
// So I can't create a handler to serve my mock requests
handler := http.HandlerFunc(Handler)

handler.ServeHTTP(rr, req)
2
  • Why pass the handler as another parameter when http.Request already supports contexts? Commented Sep 21, 2017 at 20:24
  • This is legacy code before Go1.7 the entire app was built this way. I'm just adding new routes. Still the article made it seem like this was something that could be done and was done as an example. Not sure how valid the article is now though. Commented Sep 21, 2017 at 20:26

1 Answer 1

1

httptest includes everything you need to create a fake Request and ResponseWriter for testing purposes, you just need to create an appropriate fake Context (whatever that means in your situation) and then pass all 3 to your handler function and validate what it writes to the ResponseWriter:

ctx := MakeMyContext()
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/myroute", nil)
// headers etc
MyHandler(ctx,w,r)
// Validate status, body, headers, whatever in r
Sign up to request clarification or add additional context in comments.

1 Comment

Cool, I think still will work, give me a sec to verify

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.