reticentroot
reticentroot

Reputation: 3682

How to write unit tests using httptest with handlers using context in their definitions?

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)

Upvotes: 1

Views: 1208

Answers (1)

Adrian
Adrian

Reputation: 46413

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

Upvotes: 1

Related Questions