Проверьте, была ли строка выполнена с помощью Rspec

#ruby-on-rails #email #testing #rspec

#ruby-on-rails #Адрес электронной почты #тестирование #rspec

Вопрос:

У меня есть сотрудник, который отправляет электронную почту пользователям, когда появляются новые отзывы. Я хотел разрешить пользователю не соглашаться с этим (с флагами Ши-тцу). Вопрос в следующем: как я могу проверить (с помощью Rspec) FedbackMailer.new_feedback , выполняется ли строка?

   account.users.each do |user|
    return if (user.no_notifications || user.just_summary)

    FeedbackMailer.new_feedback(account.id, feedback_id, user.id).deliver_later
  end
 

Ответ №1:

Вы можете использовать rspec-mocks .

 mailer = instance_double
allow(FeedbackMailer).to receive(:new_feedback).with(account_id, feedback_id, user_id).and_return(mailer)
allow(mailer).to receive(:deliver_later)

## do stuff ##

expect(mailer).to have_received(:deliver_later)
 

Вы также можете игнорировать .with , если у вас нет аргументов для передачи в этот момент.


Другим решением является установка конфигурации config.action_mailer.delivery_method = :test и проверка, изменилось ли количество доставок.

 
expect {
 ## code that deliver the email
}.to change { ActionMailer::Base.deliveries.count }.by(1)

 

Ответ №2:

Допустим, ваша логика инкапсулирована в следующий метод в классе MyClass

 class MyClass
  def my_method
    account.users.each do |user|
      return if (user.no_notifications || user.just_summary)

      FeedbackMailer.new_feedback(account.id, feedback_id, user.id).deliver_later
    end
  end
end

RSpec.describe MyClass, type: :model do
  context "#my_method" do
    it "should send new feedback" do
      user_obj = create_user

      expect(user_obj.no_notifications).to be_falsey
      #OR
      #expect(user_obj.just_summary).to be_falsey

      account_obj = create_account
      account_obj.users << user_obj

      expect(account_obj.users).to include(user_obj)


      expect(FeedbackMailer).to receive(:new).with(account_obj.id, feedback_id, user_obj.id)
      # OR in case you don't have feedback_id then you can use
      # expect(FeedbackMailer).to receive(:new).with(account_obj.id, kind_of(Numeric), user_obj.id)

      # You should also setup expectation here that `FeedbackMailer` gets enqueued to ensure
      # that your method also gets invoked and the job also gets enqueued.

      subject.my_method
    end
  end
end
 

Надеюсь, это поможет. Спасибо.