RSpec проверяет, был ли вызван метод

#ruby-on-rails #ruby #rspec #rspec-rails

Вопрос:

У меня есть AccountsController и действие, и destroy действие. Я хочу проверить, удаляется ли учетная запись и отменяется ли subscription она.

AccountsController

 def destroy
  Current.account.subscriptionamp;.cancel_now!
  Current.account.destroy
end
 

RSpec

 describe "#destroy" do
  let(:account) { create(:account) }
  
  it "deletes the account and cancels the subscription" do
    allow(account).to receive(:subscription)
    expect do
      delete accounts_path
    end.to change(Account, :count).by(-1)

    expect(account.subscription).to have_received(:cancel_now!)
  end
end
 

Но вышеуказанное испытание не проходит. В нем говорится:,

 (nil).cancel_now!
expected: 1 time with any arguments
received: 0 times with any arguments
 

Потому account.subscription что результаты nil , которые он показывает, показывают это. Как мне исправить этот тест?

Комментарии:

1. Ты это имел в виду expect to have_received ? Не уверен allow to have_received , что выдаст это сообщение.

2. И вы получаете это сообщение, потому Current.account что в вашем контроллере это никоим образом не связано let(:account) с вашей спецификацией. Вы возлагаете надежды на одно, но используете другое.

Ответ №1:

Вам необходимо заменить сущность учетной записи в контексте контроллера на учетную запись из теста

Это может быть

 describe "#destroy" do
  let(:account) { create(:account) }
  
  it "deletes the account and cancels the subscription" do
    allow(Current).to receive(:account).and_return(account)
    # if the subscription does not exist in the context of the account  
    # then you should stub or create it...
    expect do
      delete accounts_path
    end.to change(Account, :count).by(-1)

    expect(account.subscription).to have_received(:cancel_now!)
  end
end
 

Что касается подписки

 expect(account).to receive(:subscription).and_return(instance_double(Subscription))
# or
receive(:subscription).and_return(double('some subscription'))
# or
create(:subscription, account: account)
# or
account.subscription = create(:subscription)
# or other options ...