DEV Community

Arthur Valentim Kasper
Arthur Valentim Kasper

Posted on

How to test external APIs with Webmock and VCR in RSpec

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
Enter fullscreen mode Exit fullscreen mode

Inside the spec/scpec_helper.rb file, add the following require.

require 'webmock/rspec'
Enter fullscreen mode Exit fullscreen mode

Run the bundle install to install the gem

bundle install
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)