jarcoal/httpmock

Update resty usage example + Add JsonString responder

takanuva15 opened this issue · 1 comments

Hi, thanks for maintaining this awesome http testing library. I am using Resty to make API calls, and their documentation links to this library for mocking Client returns.

However, I am using resty@v2.12.0, which no longer offers the resty.DefaultClient which the test example in the README is currently showing:

var _ = BeforeSuite(func() {
  // block all HTTP requests
  httpmock.ActivateNonDefault(resty.DefaultClient.GetClient())
})

Instead, we have to call resty.New() and specify our own defaults. This works fine, but it doesn't work as a drop-in with the current test example, because the content-type is no longer set to application/json by default. I spent a bunch of time debugging why the readme example didn't work until I figured out that httpmock.NewStringResponder doesn't set the content/type header on the httpmock.StringResponse it's making internally. Thus Resty does not serialize the string to json automatically, so it just throws nil for the test example which is very difficult to debug.

To work around this, I had to make my own custom string responder like so:

// NewJsonStringResponder returns an httpmock Responder that resty can use to
// automatically deserialize a JSON string into a struct
func NewJsonStringResponder(status int, body string) Responder {
	res := NewStringResponse(status, body)
	res.Header.Set("Content-Type", "application/json")
	return ResponderFromResponse(res)
}

Then, it finally works with the Resty example:

client := resty.New()

var _ = BeforeSuite(func() {
  // block all HTTP requests
  httpmock.ActivateNonDefault(client.GetClient())
})

...

var _ = Describe("Articles", func() {
  It("returns a list of articles", func() {
    fixture := `{"status":{"message": "Your message", "code": 200}}`
    responder := mypackage.NewJsonStringResponder(200, fixture)
   ...
   _, err := client.R().SetResult(articleObject).Get(fakeUrl)
  })
})

Thus, I would like to request two things:

  1. Can the resty usage example be updated to work with resty@v2?
  2. Can we add NewJsonStringResponder into the httpmock library so that library users can automatically use json strings for mock responses out-of-the-box (as the resty example intended to demonstrate)? (Since json is the most common language for APIs, it makes sense to make a json-string responder function easily accessible to users without forcing them to redeclare the function I described above)

As a side note, there is a dedicated article on Medium on this library that describes the exact problem I explained above and shows the same workaround I pasted above: https://olegcodes.medium.com/mocking-http-services-in-go-6b76215a81c9

Hello,

  1. of course! could you please fill in a PR?
  2. I don't think a new function is needed as you already have several ways to do it:
    httpmock.NewStringResponder(200, `{"status":{}}`).
      HeaderSet(http.Header{"Content-Type": {"application/json"}})
    // or
    httpmock.NewJsonResponder(200, json.RawMessage(`{"status":{}}`))