2013-05-14 2 views
4

Ситуация: Проверка применения рельсов с использованием Rspec, FactoryGirl и видеомагнитофона.Использование конкретной кассеты с видеомагнитофоном по запросу

Каждый раз, когда пользователь создан, ассоциированный пользователь Stripe создается через API Stripe. Во время тестирования на самом деле нет смысла добавлять VCR.use_cassette или describe "...", vcr: {cassette_name: 'stripe-customer'} do ... к каждой спецификации, в которой задействовано создание пользователя. Мое фактическое решение заключается в следующем:

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

Но это не является устойчивым, так как та же кассета будет использоваться для каждого запроса HTTP, который, конечно, очень плохо.

Вопрос: Как я могу использовать специальные светильники (кассеты) на основе индивидуального запроса, без указания кассеты для каждой спецификации?

У меня есть что-то вроде этого в виду, псевдо-код:

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

Соответствующие части кода (как 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 

Редактировать

Я закончил делать что-то вроде это:

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 

ответ

8

VCR 2.x включает в себя функцию специально для поддержки вариантов использования, подобные этим:

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 
+0

Это отлично подходит для детального выбора кассеты, но работает только для одного запроса. Представьте себе, что мне нужно использовать другую кассету, основанную как на методе запроса, так и на uri. Возможно, я вижу это с неправильной точки зрения, но imho было бы неплохо использовать коннекторы запросов видеомагнитофона внутри 'around_http_request' для вставки конкретной кассеты на основе соответствия запроса. –

+0

Если вам нужно использовать другую кассету, основанную на методе и uri, тогда вы можете поместить любую условную логику в хук, чтобы установить имя и параметры кассеты на основе конкретного запроса. Я обновил пример, чтобы назвать кассету на основе URI запроса. Обратите внимание, что аргумент лямбда необязателен; это просто простой способ сделать крючок применимым только к некоторым запросам, поэтому вам не нужно ставить дополнительные ограничения в самом крючке. –

+0

Отлично! Большое спасибо за ваш ответ. –

2

IMO, библиотеки, подобные этому, должны быть снабжены макетным классом, но w/e.


Вы можете сделать свой псевдокод примера уже с Webmock, который по умолчанию интернет насмешливой библиотеки, которая использует VCR.

Вы можете поместить это в блок перед тем, который работает только по определенному тегу, а затем пометить запросы, которые вызывают вызовы API.


В своих тестах, они переопределяют методы, которые делегируют на RestClient (link). Вы также можете это сделать, взгляните на их тестовый набор, чтобы узнать, как они его используют, в частности, их использование test_response. Я думаю, что это ужасно хакерский способ делать что-то, и ему будет очень неудобно (обратите внимание, что я в меньшинстве с этим дискомфортом), но он должен работать на данный момент (у него есть потенциал для разрыва, без вашего ведома до времени исполнения). Если бы я сделал это, я бы хотел создать реальные объекты для двух макетов (один из насмешливых клиентов-клиентов, а другой - насмешек над ответом клиента-клиента).

+1

Я согласен, их способ сделать это действительно не так. –

-1

Весь смысл (в основном, в любом случае) видеомагнитофона, чтобы воспроизвести ответ предыдущего запроса. Если вы там выбираете и выбираете, какой ответ возвращается к какому запросу, вы делаете цитату/unquote делать-то-неправильно.

Как уже сказал Joshua, вы должны использовать Webmock для чего-то подобного. Так или иначе, видеомагнитофон находится за кулисами.

Смежные вопросы