ruby-on-railsrubytestingrspecrescue

Test a block rescue Errno::ENOENT


I saw an error that can occur when you press a button too many times and I dealt with it with a rescue, so the controller is:

 def all_list
  filename = "#{current_organization.name.gsub(' ', '_')}.zip"
  temp_file = Tempfile.new(filename)
  begin
    #things to create a zip
  rescue Errno::ENOENT
   puts 'Something went wrong'
   redirect_to all_list_report_path
  ensure
   temp_file.close
   temp_file.unlink
  end
 end

And I tried a lot of things with rspec to test this rescue block, my last try was:

  context 'with a logged user that try to' do
   before do
    login(member1.user)
    allow(ReportsController).to receive(:all_list).and_raise(Errno::ENOENT)
   end
   it 'throws the error but downloads the zip' do
    get :all_list
    expect(ReportsController).to receive(:all_list).and_raise(Errno::ENOENT)
   end
  end

It seems to work, but the block rescue is not covered and I tried to see if the block is called with puts 'Something went wrong' but obviusly does not print anything.

I'm looking for a way to cover the block effectively. Any help is welcome.


Solution

  • You have to raise the error for method which are called inside the begin block. Raising error for all_list method will never execute begin and rescue block.

    def all_list
      filename = "#{current_organization.name.gsub(' ', '_')}.zip"
      temp_file = Tempfile.new(filename)
      begin
        things_to_create_a_zip
      rescue Errno::ENOENT
       puts 'Something went wrong'
       redirect_to all_list_report_path
      ensure
       temp_file.close
       temp_file.unlink
      end
     end
    

    Allowing things_to_create_a_zip method to raise the error Errno::ENOENT, will executes the rescue block.

    context 'with a logged user that try to' do
       before do
        login(member1.user)
        allow(subject).to receive(:things_to_create_a_zip).and_raise(Errno::ENOENT)
       end
       it 'redirect to all_list_report_path' do
        get :all_list
        expect(response).to redirect_to(all_list_report_path)
       end
    end