对于上传的文件存根,Rails 5 rspec测试失败

时间:2018-01-12 12:35:45

标签: ruby-on-rails ruby rspec

在我上传文件的rspec中,我正在使用这样的函数:

 allow(ABCCLass::XYZProcessor).to receive(:prepare_processing).with(csv_statements).and_return(nil)

let(:csv_statements) do
 [fixture_file_upload('transaction.csv', 'application/csv')]
end

我得到错误: 预期的Rack :: Test :: UploadedFile 得到了ActionDispatch :: Http :: UploadedFile

这完全有意义,因为fixture_file_upload返回Rack :: Test :: UploadedFile并且使用它生成存根但是在控制器上传的文件中是Action :: Dispatch :: Uploaded file的实例。

任何想法如何创建存根并修复此问题?

回溯:

-[[#<Rack::Test::UploadedFile:0x00559d3f298100 @content_type="application/csv", @original_filename="blank.csv", @tempfile=#<Tempfile:/tmp/blank.csv20180114-293-jcb2ii>, @_filename="eur-transactions.csv">,
   -  #<Rack::Test::UploadedFile:0x00559d3f296e40 @content_type="application/csv", @original_filename="blank.csv", @tempfile=#<Tempfile:/tmp/blank.csv20180114-293-1xbpd0t>, @_filename="gbp-statement.csv">,
   -  #<Rack::Test::UploadedFile:0x00559d3f295e50 @content_type="application/csv", @original_filename="blank.csv", @tempfile=#<Tempfile:/tmp/blank.csv20180114-293-1peng22>, @_filename="internal_HSBCnet1.xls">]]
   +[[#<ActionDispatch::Http::UploadedFile:0x00559d3cb3a6a8 @tempfile=#<Tempfile:/tmp/RackMultipart20180114-293-1l9ma69.csv>, @original_filename="eur-transactions.csv", @content_type="application/csv", @headers="Content-Disposition: form-data; name=\"bank_statements[]\"; filename=\"eur-transactions.csv\"\r\nContent-Type: application/csv\r\nContent-Length: 0\r\n">,
   +  #<ActionDispatch::Http::UploadedFile:0x00559d3cb3a608 @tempfile=#<Tempfile:/tmp/RackMultipart20180114-293-17oxrrk.csv>, @original_filename="gbp-statement.csv", @content_type="application/csv", @headers="Content-Disposition: form-data; name=\"bank_statements[]\"; filename=\"gbp-statement.csv\"\r\nContent-Type: application/csv\r\nContent-Length: 0\r\n">,
   +  #<ActionDispatch::Http::UploadedFile:0x00559d3cb3a568 @tempfile=#<Tempfile:/tmp/RackMultipart20180114-293-2ukuul.xls>, @original_filename="internal_HSBCnet1.xls", @content_type="application/csv", @headers="Content-Disposition: form-data; name=\"bank_statements[]\"; filename=\"internal_HSBCnet1.xls\"\r\nContent-Type: application/csv\r\nContent-Length: 0\r\n">]]

    Please stub a default value first if message might be received with other args as well. 
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-support-3.7.0/lib/rspec/support.rb:97:in `block in <module:Support>'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-support-3.7.0/lib/rspec/support.rb:106:in `call'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-support-3.7.0/lib/rspec/support.rb:106:in `notify_failure'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/error_generator.rb:327:in `notify'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/error_generator.rb:311:in `__raise'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/error_generator.rb:60:in `raise_missing_default_stub_error'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/proxy.rb:206:in `raise_missing_default_stub_error'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/proxy.rb:191:in `message_received'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/proxy.rb:326:in `message_received'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/method_double.rb:77:in `proxy_method_invoked'
 # /root/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rspec-mocks-3.7.0/lib/rspec/mocks/method_double.rb:64:in `block (2 levels) in define_proxy_method'
 # ./app/controllers/admin/daily_adjustments/bank_transfer_deposits_controller.rb:25:in `start_process'

3 个答案:

答案 0 :(得分:0)

不应在测试中调用fixture_file_upload('transaction.csv', 'application/csv'),而应该改为返回值。

如果要存根,我会使用实例double。类似的东西:

let(:csv_statements) { instance_double(Rack::Test::UploadedFile, content_type: 'application/csv', original_filename: 'blank.csv', file_name: 'eur-transactions.csv') }

这可能无法通过复制和粘贴工作,但这将存根该类的INSTANCE,并且每当收到这些消息时,它将返回这些值。我不知道&#34; fixture_file_upload&#34;内部发生了什么,但是无论返回什么Rack :: Test :: UploadedFile对象,只需将其存根。如果你想做一个类存根,它非常相似:

let(:csv_statements) { class_double(Rack::Test::UploadedFile, content_type: 'application/csv', original_filename: 'blank.csv', file_name: 'eur-transactions.csv').as_stubbed_const }

答案 1 :(得分:0)

解决方案是使用ActionDispatch::Http::UploadedFile生成存根,目的是匹配实际函数的签名和参数。

答案 2 :(得分:0)

一个老问题,但是我最近遇到了这个问题,我正在测试是否将正确的参数传递给另一个类,包括上传的 csv 文件。

解决方法是存根 ActionDispatch::Http::UploadedFile 并使其 :new 方法返回 Rack::Test::UploadedFile: 创建的 fixture_file_upload 实例。

let(:csv_file) do
  path = Rails.root.join('spec', 'fixtures', 'test.csv')
  fixture_file_upload(path, 'text/csv')
end

before do
  allow(ActionDispatch::Http::UploadedFile).to receive(:new)
    .and_return(csv_file)
end

it 'passes csv file to class' do
  perform
  expect(MyClass).to have_received(:new).once.with(file: csv_file)
end