Let’s talk about how we can test external APIs in our applications using Webmock and VCR, for this post, I‘ll use the RSpec suite. I’ll be very straightforward and minimalist in this explanation
💎 The examples will be done in a Rails app
🌐 Webmock
The webmock gem allows us to create stubs for HTTP requests, in other words, you can create fake returns for some internet service, without making the real request.
Setting
Adding to gem file
group :test do
gem "webmock"
end
Inside the spec/scpec_helper.rb
file, add the following require
.
require 'webmock/rspec'
Run the bundle install to install the gem
bundle install
With this, the HTTP requests are disabled and the Webmock will always request the stubs of the responses, but making these stubs for all APIs can be tired, so for this, we will use VCR, which will do this “automatically” for us, so let’s see how we can do this.
📼 VCR
The VCR gem records the interaction of API calls for future usage, in other words, VCR creates a stub for us, making the real call only once and recording it in a file, to use for the next calls without making the real call again.
Setting
Adding to Gemfile
group :test do
gem "vcr"
end
Adding the code block inside of spec/scpec_helper.rb
:
VCR.configure do |config|
config.cassette_library_dir = "spec/fixtures/cassettes"
config.hook_into :webmock
config.configure_rspec_metadata!
end
The property cassette_library_dir
is about the path where the result of the APIs will be recorded, the hook_into
is about Webmock (which we talked about in the previous topic) to disable the HTTP requests when necessary and the configure_rspec_metadata!
allow us to use a property in our RSpec tests to keep them more simple using VCR, when we look at the code it will be more clear.
👨💻Testing
To show all the things I’ll make a simple get API call to JSON Placeholder in my test.
describe 'ServiceApi' do
it 'get a post', :vcr do
response = Net::HTTP.get('jsonplaceholder.typicode.com', '/posts/1')
expect(response.code).to eq '200'
end
Note that in the it
, I just add a :vcr
argument, basicly with this I already informed the RSpec that the test will use the VCR, In case you had a multiple test, it’s possible add the :vcr argument directly in the describe
.
When we ran the test, we have the following situation:
1 example, 0 failures
It passes as expected, note that a file was generated in the path that we set in cassette_library_dir
property with the name of the test, it shows that the VCR made a request and recorded the response in an yml file, now, the next time that this test runs, the RSpec will get the data from this file instead made a real API call, in case you need regenerate the response, just delete the file and rerun the test.
Cool, right? This is a very simple way to work with external APIs in our tests and ensure that we will not have intermittent fails.
Top comments (0)