4
#controller file
def update
  @payment = Payment.find_by(reference_id: params[:reference_id])
  if @payment.update(update_params)
    @payment.do_something
  end
end

when trying to spec if do_something method was called, by

expect(@payment).to receive(:do_something)

it says

expected: 1 time with any arguments
received: 0 times with any arguments

do_something is in my Payment Class. It is actually being called, but rspec says not.

Any ideas? thanks in advance

Ajay
  • 91
  • 1
  • 6

2 Answers2

4

Firstly you need to stub the lines in controller in order to expect some code

before do
  allow(Payment).to receive(:find_by).and_return(payment)
  allow(payment).to receive(:update).and_return(true)
  allow(payment).to receive(:do_something)
end

Also, instance variable in controller won't be directly accessible in rspecs.

So, First create a payment object in rspecs using let and use it before block like I did it in above solution

Nimish Gupta
  • 3,095
  • 1
  • 12
  • 20
2

Your @payment in specs is actually a totally different variable, which is part of specs class, not the controller. I may be wrong, but that is my assumption from the parts of code you post - add specs code for more info. As of the solution, may use 'stub any instance'

Payment.any_instance.stub(:do_something).and_return(:smthing)

A more complicated approach - using doubles

Denis Romanovsky
  • 298
  • 1
  • 11
  • is this equivalent to `allow_any_instance_of(Payment).to receive(:do_something).and_return(:smthing)`? – Pere Joan Martorell Aug 12 '21 at 10:10
  • now I see that `any_instance` is deprecated (see https://relishapp.com/rspec/rspec-mocks/v/3-3/docs/old-syntax/any-instance): any_instance is the old way to stub or mock any instance of a class but carries the baggage of a global monkey patch on all classes. Note that we generally recommend against using this feature. – Pere Joan Martorell Aug 12 '21 at 10:11