ruby Class.new在rspec中返回nil

时间:2016-03-25 16:48:03

标签: ruby-on-rails ruby rspec

我们正在尝试测试我们的控制器根据我们的param调用一个给定次数的类,但我们的测试在rspec中失败,说我们类的initialize方法返回nil。

我们有这个控制器:

class ProcessFaxesController < ApplicationController
  def create
    email = params["From"]
    attachment_count = params["attachment-count"].to_i
    head :ok

    if attachment_count > 0
      attachment_count.times do |document_index|
        FaxedDocumentProcessor.new(params, document_index+1).perform
      end
    else
      DocumentProcessingMailer.delay.failure_notification(email, "No attachment found.")
    end
  end
end

外部课程:

class FaxedDocumentProcessor
  def initialize(params, document_index)
    @params = params
    @attachment = @params["attachment-#{document_index}"]
    @email = @params['From']
  end

  def perform
    # some stuff here
  end
end

使用此规范:

require 'rails_helper'

RSpec.describe ProcessFaxesController, type: :controller do
  context "#create" do
    context 'with attachments' do
      before { allow_any_instance_of(FaxedDocumentProcessor).to receive(:perform).and_return(true) }

      it 'calls the FaxedDocumentProcessor attachment-count times' do
        expect(FaxedDocumentProcessor).to receive(:new).twice
        post :create, 'email' => 'test@example.com', 'attachment-count' => 2)
      end
    end
  end
end

这是我们从测试中得到的错误:

Failures:

  1) ProcessFaxesController#create with attachments calls the FaxedDocumentProcessor attachment-count times
     Failure/Error: FaxedDocumentProcessor.new(params, document_index+1).perform

     NoMethodError:
       undefined method `perform' for nil:NilClass
     # ./app/controllers/process_faxes_controller.rb:20:in `block in create'
     # ./app/controllers/process_faxes_controller.rb:19:in `times'
     # ./app/controllers/process_faxes_controller.rb:19:in `create'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/abstract_controller/base.rb:198:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/rendering.rb:10:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:117:in `call'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:505:in `call'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:778:in `_run_process_action_callbacks'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:81:in `run_callbacks'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/abstract_controller/callbacks.rb:19:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/rescue.rb:29:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/notifications.rb:164:in `block in instrument'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activesupport-4.2.6/lib/active_support/notifications.rb:164:in `instrument'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/activerecord-4.2.6/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/abstract_controller/base.rb:137:in `process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionview-4.2.6/lib/action_view/rendering.rb:30:in `process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/test_case.rb:639:in `process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/test_case.rb:67:in `process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/devise-3.5.6/lib/devise/test_helpers.rb:19:in `block in process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/devise-3.5.6/lib/devise/test_helpers.rb:72:in `catch'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/devise-3.5.6/lib/devise/test_helpers.rb:72:in `_catch_warden'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/devise-3.5.6/lib/devise/test_helpers.rb:19:in `process'
     # /Users/mary/.rvm/gems/ruby-2.3.0@website/gems/actionpack-4.2.6/lib/action_controller/test_case.rb:520:in `post'
     # ./spec/controllers/process_faxes_controller_spec.rb:22:in `block (4 levels) in <top (required)>'

我们已经尝试将binding.pry插入到控制器方法中以便自我调整,但每当我们尝试正在爆炸的调用时,我们都不会出现任何错误。

可能导致FaxedDocumentProcessor.new返回零的原因是什么?为什么我们不能在pry中重现错误?

1 个答案:

答案 0 :(得分:15)

这是由于:

造成的
expect(FaxedDocumentProcessor).to receive(:new).twice

上面的行完全存根new方法。要使其调用原始方法,请执行:

expect(FaxedDocumentProcessor).to receive(:new).twice.and_call_original

文档:https://www.relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/calling-the-original-method