Kill external requests while testing rails applications using VCR

Most recently, I had a problem with the fact that the tests of my application have been running for quite some time. This is due to the fact that some parts of the code like to access third-party services like iTunes and Facebook.
Accessing third-party services during testing is evil for the following reasons:
- If during the execution of the tests communication problems begin, they can either pass slowly or fall completely.
- As already mentioned, the speed of passing tests is quite slowed down.
- There may be problems with limiting the number of requests by the services themselves.
I was inspired to write this article by the post How to Stub External Services in Tests , which describes several techniques for getting rid of requests to external services and replacing them with local calls. The following methods are presented in the article:
- Create a stub on the sinatra, which rises while testing is in progress.
- Use the VCR library, which allows you to intercept all external requests with answers and write them to a file.
From my own experience - both approaches are good for slightly different situations. Sinatra is good when there is one small request and the response JSON is known. VCR is good when someone’s SDK is already used (in my case, Koala for communicating with Facebook) which makes a request chain to someone using the internal logic of the library.
In this article, we will focus on the use of VCR. For testing, rspec was used.
For clarity, it is worth noting that files with a query chain (and their contents) are called cassettes in the VCR ideology. This can be seen in the name of the methods and if you look at the documentation. Well, VCR itself can be literally translated as “vidic”.
First of all, we install VCR and webmock itselfto emulate requests outside. Also, webmock prohibits all external requests during tests. Gemfile:
group :testdo
...
gem 'webmock'
gem 'vcr'
...
end
Then add to spec_helper.rb:
require'webmock/rspec'require'vcr'
VCR.configure do|c|
c.cassette_library_dir = 'fixtures/vcr_cassettes'#указываем директорию где у нас будут лежать файлы с цепочками запросов
c.ignore_hosts '127.0.0.1', 'localhost'
c.hook_into :webmockend
As an example, I will give a test of my API, which subsequently makes several requests to Facebook.
This file contains a helper that registers a new test user and gives his last post from the
spec / support / fb_helper.rb feed:
moduleFbHelperdefinit_test_user
VCR.use_cassette('fb_test_user') do
result ={}
test_users = Koala::Facebook::TestUsers.new(:app_id => Rails.application.config.fb_app_id, :secret => Rails.application.config.fb_app_secret)
sandra = test_users.list.select! { |x| x["id"]=="1462678604000503" }
@sandra_token = sandra.first['access_token']
@graph = Koala::Facebook::API.new(@sandra_token)
@sender_id = @graph.get_object("me")["id"]
posts = @graph.get_connections("me", "posts")
@post_id = posts.select {|x| x['id']=="1462678604000503_1462707207330976"}.first["id"]
result[:sandra_token] = @sandra_token
result[:post_id]= @post_id
result[:sender_id] = @sender_id
return result
endendend
The test spec file itself / spec / requests / facebook_register_post_request_spec.rb:
require'spec_helper'
describe 'проверака шэринга постов в FB'do
let(:device) {
FactoryGirl.create(:device,:guid=>generate_guid)
}
it 'должен проходить с валидными токенами и постом'do
result = init_test_user
start_points = device.points
VCR.use_cassette('fb_register_post') do#используем другой файл для чтения/записи запросов
get register_fb_post_api_path,{:id=>device.guid,:post=>result[:post_id],:sender=>result[:sender_id],:token=>result[:sandra_token]}
end
expect(response).to be_success
endend
According to the experience of his small project, the speed of passing tests decreased from 25 seconds (during an unstable connection it could calmly go in 1 minute) to 8 seconds.
Full documentation for the library can be found here .