【问题标题】:Rails controller RSpec undefined method `encode' for nil:NilClass用于 nil:NilClass 的 Rails 控制器 RSpec 未定义方法“编码​​”
【发布时间】:2020-09-07 09:48:32
【问题描述】:

我有一个带有 ActiveAdmin 面板的 Rails 6 应用程序,该应用程序具有使用管理活动日志创建 CSV 文件的方法。我想为该操作创建 RSpec 测试,如下所示:

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

但它给了我一个错误:

  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

这是一个我想测试的方法(它的行为就像一个控制器)。

  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

【问题讨论】:

    标签: ruby-on-rails ruby rspec


    【解决方案1】:

    我相信问题出在allow(csv_admin_log_generator_instance).to receive(:call) 你存根这个方法,它的结果是零。你需要强制它调用原来的方法allow(csv_admin_log_generator_instance).to receive(:call).and_call_original

    【讨论】:

    • 不,我收到一个错误:<InstanceDouble(AdminLogData::CsvAdminLogGenerator) (anonymous)> is a pure test double. 'and_call_original' is only available on a partial double.
    • 尝试用let(:csv_admin_log_generator_instance) { ::AdminLogData::CsvAdminLogGenerator.new }替换let(:csv_admin_log_generator_instance) { instance_double(::AdminLogData::CsvAdminLogGenerator) }
    • 好的,现在我收到一个错误:Failure/Error: expect(csv_admin_log_generator_instance).to receive(send_data) NameError: undefined local variable or method 'send_data' for #<RSpec::ExampleGroups::AdminUsersController::ImportCsv:0x00007fd6cd4597e0>
    • 这是另一种错误。您打印错误的方法名称 send_data 应该是 :send_data,开头有一个冒号。此外,您希望csv_admin_log_generator_instance 接收send_data,但send_data 是控制器的方法而不是::AdminLogData::CsvAdminLogGenerator
    • 好的那么如何测试这样的动作呢?如果我改变期望是这样的:expect(controller).to receive(:send_data) 我收到大量错误以结尾:expected: 1 time with any arguments received: 0 times with any arguments
    【解决方案2】:

    我发现我不需要模拟任何这些方法,只需启用 paper_trail gem 并按如下方式更新规范。

    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: 'steven.hyde@example.com')
          get :import_csv
          expect(response.header['Content-Type']).to include 'text/csv'
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多