ruby Class.new returning nil in rspec

Viewed 1340

We are trying to test that our controller is calling a class a given number of times based on a param we have, but our test is failing in rspec, saying that the initialize method on our class is returning a nil.

We have this controller:

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

The external class:

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

With this spec:

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

This is the error we are getting from our test:

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)>'

We've tried inserting binding.pry into the controller method to poke around ourselves, but whenever we try the call that's blowing up, we don't get any errors.

What could be causing FaxedDocumentProcessor.new to return a nil? And why can't we reproduce the error in pry?

1 Answers
Related