Using a Specific VCR Cassette Based on Request

Situation: testing a rails application using Rspec, FactoryGirl, and VCR.

Each time a user is created, an associated Stripe user is created through the Stripe API. During testing, there really is no point in adding VCR.use_cassette or describe "...", vcr: {cassette_name: 'stripe-customer'} do ... to each specification in which user creation is involved. My actual solution is this:

 RSpec.configure do |config| config.around do |example| VCR.use_cassette('stripe-customer') do |cassette| example.run end end end 

But this is not sustainable, because the same cartridge will be used for every HTTP request, which, of course, is very bad.

Question: How can I use certain devices (cartridges) based on an individual request without specifying a cartridge for each specification?

I have something like this, pseudo code:

 stub_request(:post, "api.stripe.com/customers").with(File.read("cassettes/stripe-customer")) 

Relevant code fragments (like gist ):

 # user_observer.rb class UserObserver < ActiveRecord::Observer def after_create(user) user.create_profile! begin customer = Stripe::Customer.create( email: user.email, plan: 'default' ) user.stripe_customer_id = customer.id user.save! rescue Stripe::InvalidRequestError => e raise e end end end # vcr.rb require 'vcr' VCR.configure do |config| config.default_cassette_options = { record: :once, re_record_interval: 1.day } config.cassette_library_dir = 'spec/fixtures/cassettes' config.hook_into :webmock config.configure_rspec_metadata! end # user_spec.rb describe :InstanceMethods do let(:user) { FactoryGirl.create(:user) } describe "#flexible_name" do it "returns the name when name is specified" do user.profile.first_name = "Foo" user.profile.last_name = "Bar" user.flexible_name.should eq("Foo Bar") end end end 

Edit

I ended up doing something like this:

 VCR.configure do |vcr| vcr.around_http_request do |request| if request.uri =~ /api.stripe.com/ uri = URI(request.uri) name = "#{[uri.host, uri.path, request.method].join('/')}" VCR.use_cassette(name, &request) elsif request.uri =~ /twitter.com/ VCR.use_cassette('twitter', &request) else end end end 
+4
source share
3 answers

The 2.x VCR includes a function specifically designed to support such cases:

https://relishapp.com/vcr/vcr/v/2-4-0/docs/hooks/before-http-request-hook ! https://relishapp.com/vcr/vcr/v/2-4-0/docs/hooks/after-http-request-hook ! https://relishapp.com/vcr/vcr/v/2-4-0/docs/hooks/around-http-request-hook !

 VCR.configure do |vcr| vcr.around_http_request(lambda { |req| req.uri =~ /api.stripe.com/ }) do |request| VCR.use_cassette(request.uri, &request) end end 
+8
source

IMO, libraries like this should provide you with a mock class, but w / e.


You can make your own example of pseudocode already with Webmock , which is the public Internet library used in the VCR.

 body = YAML.load(File.read 'cassettes/stripe-customer.yml')['http_interactions'][0]['response']['body']['string'] stub_request(:post, "api.stripe.com/customers").to_return(:body => body) 

You can put this in the front block, which runs only on a specific tag, then tag requests that invoke API calls.


In their tests, they override the methods that delegate RestClient ( reference ). You can also do this, take a look at their test suite to find out how they use it, in particular, their use of test_response. I think this is a terribly hacky way to do something, and it will be very uncomfortable for him (note that I am in the minority with this discomfort), but it should work at the moment (it has the potential for a break, without your knowledge until execution time). If I did this, I would like to create real objects for two layouts (one of the mocking client clients and the other mocking the client response).

+2
source

The whole point (basically, in any case) of the VCR is simply to reproduce the response of the previous request. If you choose there and choose which answer returns to which query, you quote / unquote do-it-wrong.

As Joshua already said, you should use Webmock for something like that. In any case, that VCR is behind the scenes.

-1
source

Source: https://habr.com/ru/post/1480618/


All Articles