Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec Throws ArgumentError with or without arguments

I'm trying to write a fairly straightforward test on a service object that handles an error. Rails version 5.2 and Rspec 3.8.

app/services/application_service.rb

class ApplicationService
  def self.call(*args, &block)
    new(*args, &block).call
  end
end

app/services/basic_objects/create_payment.rb

  module BasicObjects
    class CreatePayment < ApplicationService
      def initialize(args)
        @transaction_id = args[:transaction_id]
      end

      def call
        transaction = Transaction.find(@transaction_id)
        payment = Payment.new(transaction: transaction)
        payment.save
      rescue CustomError => e
        if /waiting/i === e.message
          puts "Ignoring exception \"#{e.message}\" to prevent retry"
        else
          raise e
        end
      end
    end

Here is the test

describe BasicObjects::CreatePayment, type: :model do
  describe '#call' do
    let(:params) { { transaction_id: "xyz" } }

    context 'when there is a rescued error' do
      before do
        allow_any_instance_of(Payment)
          .to receive(:save)
          .and_raise(CustomError, "waiting")
      end

      it 'does not raise an error' do
         expect { described_class.call(params) }.not_to raise_error
      end
    end
  end
end

And it responds with this error: expected no Exception, got #<ArgumentError: wrong number of arguments (given 1, expected 0)

But if I remove the params and instead expect(described_class.call).not_to raise_error I get an error from not sending the argument

<BasicObjects::CreatePayment (class)> received :call with unexpected arguments
         expected: ({:transaction_id=>"xyz"})
              got: (no args)

So, then I remove with(params) from the allow statement

context 'when there is a rescued error' do
    before do
      allow(described_class).to receive(:call).and_raise(CustomError, "waiting")
    end

    it 'does not raise an error' do
       expect(described_class.call).not_to raise_error
    end
  end

And I get

ArgumentError:
       wrong number of arguments (given 1, expected 0)

Any help is greatly appreciated

UPDATE I have adjusted the call above to raise the error on a line in the class, rather than just in calling the class itself. However, I am still getting the same error: expected no Exception, got #<ArgumentError: wrong number of arguments (given 1, expected 0)>

like image 992
Carl Avatar asked Apr 14 '26 16:04

Carl


1 Answers

I ran into a similar problem and the <ArgumentError: wrong number of arguments (given 1, expected 0)> was very misleading and confusing.

Given your example, the problem is likely that your CustomError class's initialize method takes 0 argument and you are passing the "waiting" string as part of your mock, ie. allow_any_instance_of(Payment).to receive(:save).and_raise(CustomError, "waiting").

The error message is actually complaining that you are passing the wrong number of arguments in your exception as your mocked exception is raised. So this should be fixed by removing "waiting":

allow_any_instance_of(Payment)
  .to receive(:save)
  .and_raise(CustomError)
like image 81
Frank Kwok Avatar answered Apr 17 '26 07:04

Frank Kwok



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!