Тестирование таких асинхронных вещей всегда сложно.Что мы делаем:
В наших функциональных тестах мы проверяем, что задание ставится в очередь.Обычно достаточно употребления мокко или чего-то подобного с ожиданием.Если вы хотите запустить тестовый сервер Redis, вы можете проверить правильность увеличения очереди и правильность параметров задания.Хотя вы тестируете Resque себя немного в этот момент.
Задания тестируются изолированно как модульные тесты.Поскольку у них просто есть метод класса с именем perform
, ваши модульные тесты довольно просты.В вашем случае вы должны проверить, что ChangeRecorderJob.perform делает то, что вы хотите.Мы склонны проверять, что задания находятся в соответствующей очереди, что параметры задания верны и что задание выполняет то, что мы хотим.
Теперь, чтобы проверить все вместе,сложная часть.Я сделал это двумя разными способами, и у каждого есть свои плюсы и минусы:
- Monkey-patch Resqueue.enqueue для синхронного запуска задания Начиная с resque 1.14.0вы можете использовать
Resque.inline = true
в своем инициализаторе вместо патчей для обезьян - Имитировать работника, выталкивающего задание из очереди и фактически выполняемого в разветвленном процессе
Синхронный запуск задания намного проще.Вы бы просто загрузили что-то вроде следующего в ваш spec_helper:
module Resque
alias_method :enqueue_async, :enqueue
def self.enqueue(klass, *args)
klass.new(0, *args).perform
end
end
Начиная с версии 1.14.0 вы можете просто установить Resque.inline = true
в инициализаторевместо обезьяны-исправления.Если вы застряли на более старой версии resque, необходим обезьян-патч.
Обратите внимание, что, поскольку вы работаете здесь синхронно, вы будете нести расходы на длительную работу.работа.Возможно, более важно то, что вы собираетесь работать в одном и том же процессе, так что это не совсем точное представление о том, как ваша работа будет выполняться.
Запускать работу в разветвленном рабочем режиме, очень похоже на resqueвам нужно будет сделать что-то вроде следующего:
def run_resque_job(job_class, job_args, opts={})
queue = opts[:queue] || "test_queue"
Resque::Job.create(queue, job_class, *job_args)
worker = Resque::Worker.new(queue)
worker.very_verbose = true if opts[:verbose]
if opts[:fork]
# do a single job then shutdown
def worker.done_working
super
shutdown
end
worker.work(0.01)
else
job = worker.reserve
worker.perform(job)
end
end
Существует небольшая задержка в том, чтобы заставить работника выбросить задание из очереди.И, естественно, вам понадобится запустить тестовый сервер Redis, чтобы у работника была очередь, с которой нужно выскочить.
Я уверен, что другие люди придумали хитрые способы тестирования заданий Resque.Это то, что работает для меня.