I have a rake task that guards against dangerous Rails rake rasks, based on the environment. It works fine. When I test each individual dangerous method in RSpec, the test passes. When I test multiple in a row, for multiple environments, the test fails after the first one. Even if I run the test multiple times for the same dangerous action, rake db:setup
for example, it will only pass the first time. If I run the tests as individual it
statements, one for each dangerous action, only the first two will pass (there are 4).
How can I get RSpec to behave correctly here, and pass all the tests when run in a suite?
The rake task
# guard_dangerous_tasks.rake
class InvalidTaskError < StandardError; end
task :guard_dangerous_tasks => :environment do
unless Rails.env == 'development'
raise InvalidTaskError
end
end
%w[ db:setup db:reset ].each do |task|
Rake::Task[task].enhance ['guard_dangerous_tasks']
end
The RSpec test
require 'spec_helper'
require 'rake'
load 'Rakefile'
describe 'dangerous_tasks' do
context 'given a production environment' do
it 'prevents dangerous tasks' do
allow(Rails).to receive(:env).and_return('production')
%w[ db:setup db:reset ].each do |task_name|
expect { Rake::Task[task_name].invoke }.to raise_error(InvalidTaskError)
end
end
end
context 'given a test environment' do
it 'prevents dangerous tasks' do
allow(Rails).to receive(:env).and_return('test')
%w[ db:setup db:reset ].each do |task_name|
expect { Rake::Task[task_name].invoke }.to raise_error(InvalidTaskError)
end
end
end
end
RSpec Output
# we know the guard task did its job,
# because the rake task didn't actually run.
Failure/Error: expect { Rake::Task[task_name].invoke }.to raise_error(InvalidTaskError)
expected InvalidTaskError but nothing was raised
puts
. – Martimartial