Reputation: 4503
I am using VCR to record http interactions with an external API. This is my (working) code:
it 'does xyz....' do
hook_payload = {ruby_hash: 'here'}
VCR.use_cassette('my_folder/create_project') do
VCR.use_cassette('my_folder/get_project') do
update = Update.new(hook_payload)
expect { update.call }.to change { Projects.count }.by(1)
end
end
end
The code above works, but the organization isn't good, as I prefer to have the expect{}
call outside the block. So, I tried this, but the following code does not work:
context 'my context', vcr: { group: 'my_folder', cassettes: %w[create_project get_project] } do
it 'does xyz....' do
hook_payload = {ruby_hash: 'here'}
update = Update.new(hook_payload)
expect { update.call }.to change { Projects.count }.by(1)
end
However this code doesn't work and I get the following error:
VCR is currently using the following cassette: - /Users/me/this_project/spec/fixtures/vcr/my_folder/create_project.yml.
Under the current configuration VCR can not find a suitable HTTP interaction to replay and is prevented from recording new requests.
I am 100% sure that my_folder/get_project.yml
is valid, and it works in other tests in the project.
I even put the cassettes (%w[create_project get_project]
) in the same order that they are used in my code. What am I doing incorrectly here?
Upvotes: 15
Views: 6748
Reputation: 38428
It's recommended to use the block but there are options if you don't want to do that. There are two ways: use an around hook or a before and an after hook.
If you load cassettes manually, you'll need to eject them if you reuse cassettes between tests as they don't like being loaded twice (the VCR analogy holds well here!).
https://www.rubydoc.info/github/vcr/vcr/VCR:insert_cassette
Try using VCR.insert_cassette
which does not require a block. You'll need to call eject_cassette
in your tear downs. I tried it and it worked. The ordering doesn't matter.
it 'does xyz....' do
hook_payload = {ruby_hash: 'here'}
VCR.insert_cassette('my_folder/create_project')
VCR.insert_cassette('my_folder/get_project')
update = Update.new(hook_payload)
expect { update.call }.to change { Projects.count }.by(1)
end
Call eject to avoid loading cassettes twice:
VCR.eject_cassette(name: 'my_folder/create_project')
VCR.eject_cassette(name: 'my_folder/get_project')
The around hook might work for you too:
around do |example|
cassettes = [
{ name: 'my_folder/create_project' },
{ name: 'my_folder/get_project' }
]
VCR.use_cassettes cassettes do
example.run
end
end
You can even combine this with cassette config:
it 'whateva', vcr: { cassette_name: 'load another' } do
end
Upvotes: 5