Previously I covered github.com/h2non/gock
, that package is used for testing HTTP requests, the way it works is by manually mocking both requests and responses, this time we are taking a different approach and instead of doing that we are saving both the requests and responses as fixtures for replaying them in future tests.
Please refer to the full example code for more details.
Let me introduce to you github.com/dnaeon/go-vcr
.
Using dnaeon/go-vcr
The way this package works is by injecting as a http.RoundTripper
assigned to the Transport
field in the used http.Client
, for example:
// recorder is "github.com/dnaeon/go-vcr/recorder"
r, err := recorder.New(path.Join("fixtures", "weather_401"))
if err != nil {
t.Fatalf("failed creating recorder %s", err)
}
return &http.Client{Transport: r}, r.Stop
The first time this code is run it would create a new file called fixtures/weather_401.yaml
, if it does not exist, saving all the information related to requests, including things such as query arguments and headers, as well as the responses received after.
The idea behind saving this file is to have a deterministic way to get the same same results when running the same tests in the future. dnaeon/go-vcr
behind the scenes uses that file to properly match the request and return the responses that were previously saved.
Removing secrets
There are cases where we are actually using real credentials, either as HTTP headers or query arguments, dnaeon/go-vcr
allows you to remove those so we don't leak them, for example:
r, err := recorder.New(path.Join("fixtures", "weather_200"))
if err != nil {
t.Fatalf("failed creating recorder %s", err)
}
cleanURL := func(u *url.URL) *url.URL {
q := u.Query()
q.Del("appid")
u.RawQuery = q.Encode()
return u
}
r.AddFilter(func(i *cassette.Interaction) error {
u, err := url.Parse(i.Request.URL)
if err != nil {
return err
}
i.URL = cleanURL(u).String()
return nil
})
r.SetMatcher(func(r *http.Request, i cassette.Request) bool {
r.URL = cleanURL(r.URL)
return cassette.DefaultMatcher(r, i)
})
return &http.Client{Transport: r}, r.Stop
In the case above we are both:
- Removing a query argument in the request, and
- Updating the matcher to not consider that value.
By doing that we are able to deterministically run our tests afterwards.
Final thoughts
dnaeon/go-vcr
and h2non/gock
complement each other, go-vcr
is useful when working with third party APIs where only a few fields are used, it allows future us to refer to the saved fixtures to make decisions regarding things like adding support for using already known fields or make decisions about the possible options available on the third party API.
In the end dnaeon/go-vcr
is a must, highly recommended.
Top comments (0)