Often our application interacts with different web services, in order to test it we need to do some preparations to be able to stub those requests and then if they take a lot of time to proceed - to replay the records of it without repeating real requests.
To install VCR we need to add two gems to the test group, gem webmock will be installed as a dependancy and will handle all the external requests, there are some more libraries supported (fakeweb is deprecated in VCR 3.0).
#Gemfile
group :test do
gem 'vcr'
gem 'webmock'
end
#install
bundle install
In order to configure VCR we should create the configuration file vcr.rb inside the folder 'spec/support' and put there a few lines of code:
# vcr.rb
VCR.configure do |c|
#Define a folder where VCR will save it's cassettes
c.cassette_library_dir = Rails.root.join('spec','vcr')
#Define the library with will handle HTTP requests
c.hook_into :webmock
end
RSpec.configure do |c|
#Can provide tags without 'true'
c.treat_symbols_as_metadata_keys_with_true_values = true
#Pick up options from specs with tag 'vcr' and save the cassette with spec name
c.around(:each, :vcr) do |example|
#Get the cassette name from spec name
name = example.metadata[:full_description].split(/\s+/, 2).join("/").underscore.gsub(/[^\w\/]+/, "_")
#Get options record and match_requests_on from tags, we can add some options
options = example.metadata.slice(:record, :match_requests_on).except(:example_group)
#Use cassette for this spec example
VCR.use_cassette(name, options) { example.call }
end
end
Now if RSpec finds a test with tag :vcr
it begins to search for option tags, one of them is
:record
which provide the settings for cassette. This option can accept following values:
:record => :all #Records request every time you execute it
:record => :once #Records request once or if there is no cassette for this spec
:record => :new_episodes #Records request if resonse has differences (???)
:record => :none #Replay previously recorded interactions, raise error in other cases
If your request requires NTLM authorization you could make the following setting of Webmock
WebMock.allow_net_connect!(:net_http_connect_on_start => true)
before execute it.
before(:each) do
WebMock.allow_net_connect!(:net_http_connect_on_start => true)
end
describe 'some_external_request', :vcr, record: :all do
#spec body
end
It is very important to have your cassette up to date thats why we should try to push our cassettes in one commit with message describing a list of cassettes and timestamps. For example:
#Commit message
Add new VCR cassets
some_ws_interaction_get : xx.xx.20xx
...
some_ws_interaction_post : xx.xx.20xx
Great @SblSsS! : ) That's really nice!