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
Ответы
Ответ 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
Это, похоже, работает на моей стороне и позволяет мне запускать как мои замедленные задания, так и мои методы.