mr_muscle
mr_muscle

Reputation: 2910

Rails controller RSpec undefined method `encode' for nil:NilClass

I've got a Rails 6 app with an ActiveAdmin panel which has a method of creating CSV files with admin activities logs. I want to create RSpec test for that action like below:

admin/users_spec.rb

describe Admin::UsersController, type: :controller do
  include Devise::Test::ControllerHelpers

  before { sign_in admin }

  let!(:admin) { create(:admin_user) }

  describe '#import_csv' do
    let(:csv_admin_log_generator_instance) { instance_double(::AdminLogData::CsvAdminLogGenerator) }

    before do
      allow(::AdminLogData::CsvAdminLogGenerator).to receive(:new).and_return(csv_admin_log_generator_instance)
      allow(csv_admin_log_generator_instance).to receive(:call)
      get :index
    end

    it 'accepts send_data' do
      get :import_csv
      expect(csv_admin_log_generator_instance).to receive(send_data)
    end
  end
end

But it gives me an error:

  1) Admin::UsersController#import_csv accepts send_data
     Failure/Error:
       send_data file.encode('UTF-8'), type: 'text/csv; charset=UTF-8; header=present',
                                       disposition: 'attachment; filename=admin_logs.csv'

     NoMethodError:
       undefined method `encode' for nil:NilClass

Here is a method which I want to test (it behaves like a controller).

  collection_action :import_csv, method: :get do
    file = ::AdminLogData::CsvAdminLogGenerator.new.call

    send_data file.encode('UTF-8'), type: 'text/csv; charset=UTF-8; header=present',
                                    disposition: 'attachment; filename=admin_logs.csv'
  end

Upvotes: 0

Views: 728

Answers (2)

mr_muscle
mr_muscle

Reputation: 2910

I figured out that I don't need to mock any of those methods but just simply enable paper_trail gem and update specs as follows.

describe Admin::UsersController, type: :controller do
  include Devise::Test::ControllerHelpers

  let!(:admin) { create(:admin_user) }
  before do
    sign_in admin
    get :index
  end

  it_behaves_like 'controller response status', 200

  describe '#import_csv' do
    it_behaves_like 'controller response status', 200

    it 'create CSV file', versioning: true do
      admin.update!(email: '[email protected]')
      get :import_csv
      expect(response.header['Content-Type']).to include 'text/csv'
    end
  end
end

Upvotes: 0

Yakov
Yakov

Reputation: 3201

I believe the problem is here allow(csv_admin_log_generator_instance).to receive(:call) you stub this method and the result of it is nil. You need to force it to call the original method allow(csv_admin_log_generator_instance).to receive(:call).and_call_original

Upvotes: 0

Related Questions