Подтвердить что ты не робот

Rails/Rspec: проверка сообщений delayed_job

Просто интересно, как проверить, что запросы actionmailer действительно отправлены в delayed_job que в rspec.

Я бы предположил, что это было довольно просто, но моя очередь delayed_job, похоже, не увеличивается. Код ниже:

Контроллер:

  def create
    @contact = Contact.new(params[:contact])
      if @contact.save
        contactmailer = ContactMailer
        contactmailer.delay.contact_message(@contact)
        redirect_to(contacts_url)
      else
        render :action => "new"
      end

Spec:

  it "queues mail when a contact is created" do
    expectedcount = Delayed::Job.count + 1
    Contact.stub(:new).with(mock_contact()) { mock_contact(:save => true) }
    post :create, :contact => mock_contact
    expectedcount.should eq(Delayed::Job.count)
  end

Как до, так и после вызова контроллера, Delayed:: Job.count возвращает 0. Я попытался вынести условие из контроллера, но я до сих пор не могу получить отложенное количество заданий для увеличения.

Любые предложения, оцененные - cheer

4b9b3361

Ответ 1

Вы также можете проверить, какие задания будут выполняться, запустив их или отключив очередь.

Конфигурируйте конфигурацию всякий раз, когда захотите (т.е. в блоке before :each).

Delayed::Worker.delay_jobs = false

или выполнить сохраненные задания

Delayed::Worker.new.work_off.should == [1, 0]

Я использую этот метод долгое время. Во-первых, используя новую поддержку any_instance в RSpec, вы можете напрямую протестировать свои эффекты с задержкой. Тем не менее, я нашел тесты, которые используют work_off для замедления.

Что я обычно делаю сейчас:

mock_delay = double('mock_delay').as_null_object
MyClass.any_instance.stub(:delay).and_return(mock_delay)
mock_delay.should_receive(:my_delayed_method)

Тогда у меня есть отдельная спецификация для my_delayed_method. Это намного быстрее и, вероятно, более эффективная практика тестирования модулей, особенно для контроллеров. Хотя, если вы выполняете спецификации запросов или другие спецификации уровня интеграции, вы, вероятно, все еще хотите использовать work_off.

Ответ 2

Я думаю, что ваш макет-объект каким-то образом вводит ошибку - трудно точно сказать, как не увидеть определение метода mock_contact.

В любом случае вы можете попробовать что-то в этом направлении:

  it "queues mail when a contact is created" do
    Contact.stub(:new) { mock_model(Contact,:save => true) }
    Delayed::Job.count.should == 0
    post :create, {}
    Delayed::Job.count.should == 1
  end

или более сексуальная версия (предостережение: я всегда делаю это без секса):

  it "queues mail when a contact is created" do
    Contact.stub(:new) { mock_model(Contact,:save => true) }
    expect {
      post :create, {}
    }.to change(Delayed::Job.count).by(1)
  end

Ответ 3

Вы также можете следовать соглашению (Railscast 275)

    ActionMailer::Base.deliveries.last.to.should == user.email

но вместо этого сделайте следующее:

    Delayed::Job.last.handler.should have_content(user.email)

Ответ 4

@zetetic Я думаю, что мы должны передать блок в методе изменения здесь.

Это будет так:

it "queues mail when a contact is created" do
Contact.stub(:new) { mock_model(Contact,:save => true) }
expect {
    post :create, {}
  }.to change { Delayed::Job.count }.by(1)
end

Ответ 5

Этот поток немного устарел, но вот мой ход:

Создать функцию expect_jobs

def expect_jobs n, time = nil
  expect(Delayed::Job.count).to eq(n)
  Timecop.travel(time) unless time.nil?
  successes, failures = Delayed::Worker.new.work_off
  expect(successes).to eq(n)
  expect(failures).to eq(0)
  expect(Delayed::Job.count).to eq(0)
  Timecop.travel(Time.now) unless time.nil?
end

Затем просто вызовите его, прежде чем проверять, выполнил ли обратный вызов свою работу. например:

it "sends a chapter to the admin user" do
  post :chapter_to_user, { chapter: @book.chapters.first}
  expect_jobs(1)
  SubscribeMailer.should have(1).delivery
  SubscribeMailer.deliveries.should have(1).attachment
end

Это, похоже, работает на моей стороне и позволяет мне запускать как мои замедленные задания, так и мои методы.