Skip to content

Instantly share code, notes, and snippets.

@alex-sysoev
Last active August 29, 2015 14:05
Show Gist options
  • Save alex-sysoev/d56f6293e80fd929b1a0 to your computer and use it in GitHub Desktop.
Save alex-sysoev/d56f6293e80fd929b1a0 to your computer and use it in GitHub Desktop.
Test Web Services with VCR

Testing Web Services with RSpec & VCR

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.

Installation

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

Configuration

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

Usage

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.

Example

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

Cassete versioning

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
@gonzalo-bulnes
Copy link

Great @SblSsS! : ) That's really nice!

@gertfindel
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment