Ситуация: Проверка применения рельсов с использованием 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
Это отлично подходит для детального выбора кассеты, но работает только для одного запроса. Представьте себе, что мне нужно использовать другую кассету, основанную как на методе запроса, так и на uri. Возможно, я вижу это с неправильной точки зрения, но imho было бы неплохо использовать коннекторы запросов видеомагнитофона внутри 'around_http_request' для вставки конкретной кассеты на основе соответствия запроса. –
Если вам нужно использовать другую кассету, основанную на методе и uri, тогда вы можете поместить любую условную логику в хук, чтобы установить имя и параметры кассеты на основе конкретного запроса. Я обновил пример, чтобы назвать кассету на основе URI запроса. Обратите внимание, что аргумент лямбда необязателен; это просто простой способ сделать крючок применимым только к некоторым запросам, поэтому вам не нужно ставить дополнительные ограничения в самом крючке. –
Отлично! Большое спасибо за ваш ответ. –