In my cucumber support directory I have the following in vcr.rb:
require 'vcr'
VCR.configure do |c|
c.cassette_library_dir = 'fixtures/vcr_cassettes'
c.hook_into :webmock
c.ignore_localhost = true
c.default_cassette_options = { record: :new_episodes }
end
I am geocoding city names which makes calls to the Google Maps API. I'm trying to record and stub these requests, but it keeps recording the same requests to the same yml file:
- request:
method: get
uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- ! '*/*'
User-Agent:
- Ruby
# response...
- request:
method: get
uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- ! '*/*'
User-Agent:
- Ruby
It's the same URL and very same request, shouldn't VCR stub the request? How can I prevent my specs from hitting the API every time I try to search for the same city?
It's hard to say for sure what's going on with just what you've posted, but I can explain a bit more about how VCR works and make some guesses about possible reasons for this behavior.
VCR uses request matchers to try to find a previously recorded HTTP interaction to play back. During a single cassette session, when an HTTP interaction is played back, it is considered to be "used" and it will not be played back again (unless you use the allow_playback_repeats option).
So...here are a couple possibilities that come to mind:
:allow_playback_repeats
(which is the default, and how I recommend you use VCR), then the behavior you're seeing could happen if multiple duplicate requests are being made in your test--e.g., maybe the cassette has only one matching request but you're test makes 2 of them--that would play back one and record one (since you're using :new_episodes
).To troubleshoot this, I recommend you use the debug_logger option to get VCR to print what it's doing and how it's trying to match each request. That should give you insight into what's going on. You can also override any of the built in request matchers and provide your own logic and/or set a breakpoint in the matcher:
VCR.configure do |c|
c.register_request_matcher :uri do |request_1, request_2|
debugger # so you can inspect the requests here
request_1.uri == request_2.uri
end
end
You may also have run into a VCR bug, although comparing the URIs (using String#==
) is such a basic operation that I have a hard time imagining a bug there. Feel free to open a github issue (hopefully with the debug logger output and/or a code sample that triggers this) if you can't figure it out.
On a side note, I recommend you use the :once
record mode (the default) rather than :new_episodes
. :once
will never record additional HTTP interactions to an existing cassette--it only allows the cassette to be recorded once. If a request fails to match, it'll raise an error alerting you to the fact it couldn't match. :new_episodes
, on the other hand, will record any request that it can't find a match for, which is the behavior you're seeing.