What I want: External API calls to return the same thing each time the tests run What I get: First time VCR saves it, second time Typhoeus returns an error
What happens is I run the test once, it makes the actual requests (that happens when I create an organization and user), and then when I run it again it can't parse the request correctly.
First run:
1) AccountSettingsController GET #show responds successfully with an HTTP 200 status code
Failure/Error: expect(response).to be_success
expected success? to return true, got false
# ./spec/controllers/account_settings_spec.rb:12:in `block (3 levels) in <top (required)>'
All the following runs until I delete the cassette:
1) AccountSettingsController GET #show responds successfully with an HTTP 200 status code
Failure/Error: organization = Fabricate(:organization)
NoMethodError:
undefined method `>=' for nil:NilClass
# ./app/models/hand.rb:45:in `create'
# ./app/models/hand.rb:64:in `save'
# ./app/models/hand.rb:70:in `save!'
# ./spec/controllers/account_settings_spec.rb:6:in `block (3 levels) in <top (required)>'
Which traces back to these lines (from a private gem I use)
def create(values)
response = Typhoeus.post(resource_url, {body: values.to_json}.merge(headers))
process_as_json response.options[:response_body]
end
def process_as_json(response)
if !response.empty?
JSON.parse(response)
else
nil
end
end
Versions:
- VCR (2.9.0)
- Webmock (1.18.9)
- Typhoeus (0.6.8)
Setup:
# spec/spec_helper.rb
require "simplecov"
SimpleCov.start "rails"
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../config/environment", __FILE__)
require "rspec/rails"
require "rspec/autorun"
require "capybara/rspec"
require "webmock/rspec"
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
Fabrication.configure do |config|
config.path_prefix = Rails.root
end
VCR.configure do |config|
config.cassette_library_dir = "spec/vcr_cassettes"
config.hook_into :webmock
config.configure_rspec_metadata!
end
RSpec.configure do |config|
config.order = "random"
config.treat_symbols_as_metadata_keys_with_true_values = true
end
Test:
# spec/controllers/account_settings_spec.rb
require "spec_helper"
describe AccountSettingsController do
describe "GET #show" do
it "responds successfully with an HTTP 200 status code", :vcr do
organization = Fabricate(:organization)
user = Fabricate(:user, organization_id: organization.id)
get :show
expect(response).to be_success
expect(response.status).to eq(200)
end
end
end
There's no way to definitively answer your question from the details you've provided but here's a few suggestions:
hook_into :typhoeus
rather thanhook_into :webmock
. VCR's able to record and playback more accurately when you hook directly into typhoeus rahter than using webmock as an intermediary layer.