Created
October 8, 2015 09:03
-
-
Save arturictus/bbdf020b2deca2e29c94 to your computer and use it in GitHub Desktop.
Translating AtiveJob::TestHelper to Rspec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def specific_enqueued_jobs(job) | |
enqueued_jobs.select{ |j| j if j[:job] == job } | |
end | |
require 'active_support/core_ext/class/subclasses' | |
require 'active_support/core_ext/hash/keys' | |
module ActiveJob | |
# Provides helper methods for testing Active Job | |
module RSpecHelper | |
extend ActiveSupport::Concern | |
included do | |
def before_setup # :nodoc: | |
test_adapter = ActiveJob::QueueAdapters::TestAdapter.new | |
@old_queue_adapters = (ActiveJob::Base.subclasses << ActiveJob::Base).select do |klass| | |
# only override explicitly set adapters, a quirk of `class_attribute` | |
klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter) | |
end.map do |klass| | |
[klass, klass.queue_adapter].tap do | |
klass.queue_adapter = test_adapter | |
end | |
end | |
clear_enqueued_jobs | |
clear_performed_jobs | |
super | |
end | |
def after_teardown # :nodoc: | |
super | |
@old_queue_adapters.each do |(klass, adapter)| | |
klass.queue_adapter = adapter | |
end | |
end | |
# Asserts that the number of enqueued jobs matches the given number. | |
# | |
# def test_jobs | |
# expect_enqueued_jobs 0 | |
# HelloJob.perform_later('david') | |
# expect_enqueued_jobs 1 | |
# HelloJob.perform_later('abdelkader') | |
# expect_enqueued_jobs 2 | |
# end | |
# | |
# If a block is passed, that block should cause the specified number of | |
# jobs to be enqueued. | |
# | |
# def test_jobs_again | |
# expect_enqueued_jobs 1 do | |
# HelloJob.perform_later('cristian') | |
# end | |
# | |
# expect_enqueued_jobs 2 do | |
# HelloJob.perform_later('aaron') | |
# HelloJob.perform_later('rafael') | |
# end | |
# end | |
# | |
# The number of times a specific job is enqueued can be asserted. | |
# | |
# def test_logging_job | |
# expect_enqueued_jobs 2, only: LoggingJob do | |
# LoggingJob.perform_later | |
# HelloJob.perform_later('jeremy') | |
# end | |
# end | |
require 'rspec/expectations' | |
RSpec::Matchers.define :have_enqueued_jobs do |expected| | |
match do |actual| | |
actual == expected | |
end | |
failure_message do |actual| | |
"#{expected} jobs expected, but #{actual} were enqueued" | |
end | |
end | |
def expect_enqueued_jobs(number, only: nil) | |
if block_given? | |
original_count = enqueued_jobs_size(only: only) | |
yield | |
new_count = enqueued_jobs_size(only: only) | |
expect(number).to have_enqueued_jobs(new_count - original_count) | |
else | |
actual_count = enqueued_jobs_size(only: only) | |
expect(number).to have_enqueued_jobs(actual_count) | |
end | |
end | |
# Asserts that no jobs have been enqueued. | |
# | |
# def test_jobs | |
# expect_no_enqueued_jobs | |
# HelloJob.perform_later('jeremy') | |
# expect_enqueued_jobs 1 | |
# end | |
# | |
# If a block is passed, that block should not cause any job to be enqueued. | |
# | |
# def test_jobs_again | |
# expect_no_enqueued_jobs do | |
# # No job should be enqueued from this block | |
# end | |
# end | |
# | |
# It can be asserted that no jobs of a specific kind are enqueued: | |
# | |
# def test_no_logging | |
# expect_no_enqueued_jobs only: LoggingJob do | |
# HelloJob.perform_later('jeremy') | |
# end | |
# end | |
# | |
# Note: This assertion is simply a shortcut for: | |
# | |
# expect_enqueued_jobs 0, &block | |
def expect_no_enqueued_jobs(only: nil, &block) | |
expect_enqueued_jobs 0, only: only, &block | |
end | |
# Asserts that the number of performed jobs matches the given number. | |
# If no block is passed, <tt>perform_enqueued_jobs</tt> | |
# must be called around the job call. | |
# | |
# def test_jobs | |
# expect_performed_jobs 0 | |
# | |
# perform_enqueued_jobs do | |
# HelloJob.perform_later('xavier') | |
# end | |
# expect_performed_jobs 1 | |
# | |
# perform_enqueued_jobs do | |
# HelloJob.perform_later('yves') | |
# expect_performed_jobs 2 | |
# end | |
# end | |
# | |
# If a block is passed, that block should cause the specified number of | |
# jobs to be performed. | |
# | |
# def test_jobs_again | |
# expect_performed_jobs 1 do | |
# HelloJob.perform_later('robin') | |
# end | |
# | |
# expect_performed_jobs 2 do | |
# HelloJob.perform_later('carlos') | |
# HelloJob.perform_later('sean') | |
# end | |
# end | |
# | |
# The block form supports filtering. If the :only option is specified, | |
# then only the listed job(s) will be performed. | |
# | |
# def test_hello_job | |
# expect_performed_jobs 1, only: HelloJob do | |
# HelloJob.perform_later('jeremy') | |
# LoggingJob.perform_later | |
# end | |
# end | |
# | |
# An array may also be specified, to support testing multiple jobs. | |
# | |
# def test_hello_and_logging_jobs | |
# assert_nothing_raised do | |
# expect_performed_jobs 2, only: [HelloJob, LoggingJob] do | |
# HelloJob.perform_later('jeremy') | |
# LoggingJob.perform_later('stewie') | |
# RescueJob.perform_later('david') | |
# end | |
# end | |
# end | |
RSpec::Matchers.define :have_performed_jobs do |expected| | |
match do |actual| | |
actual == expected | |
end | |
failure_message do |actual| | |
"#{expected} jobs expected, but #{actual} were performed" | |
end | |
end | |
def expect_performed_jobs(number, only: nil) | |
if block_given? | |
original_count = performed_jobs.size | |
perform_enqueued_jobs(only: only) { yield } | |
new_count = performed_jobs.size | |
expect(number).to have_performed_jobs(new_count - original_count) | |
else | |
performed_jobs_size = performed_jobs.size | |
expect(number).to have_performed_jobs(performed_jobs_size) | |
end | |
end | |
# Asserts that no jobs have been performed. | |
# | |
# def test_jobs | |
# expect_no_performed_jobs | |
# | |
# perform_enqueued_jobs do | |
# HelloJob.perform_later('matthew') | |
# expect_performed_jobs 1 | |
# end | |
# end | |
# | |
# If a block is passed, that block should not cause any job to be performed. | |
# | |
# def test_jobs_again | |
# expect_no_performed_jobs do | |
# # No job should be performed from this block | |
# end | |
# end | |
# | |
# The block form supports filtering. If the :only option is specified, | |
# then only the listed job(s) will be performed. | |
# | |
# def test_hello_job | |
# expect_performed_jobs 1, only: HelloJob do | |
# HelloJob.perform_later('jeremy') | |
# LoggingJob.perform_later | |
# end | |
# end | |
# | |
# An array may also be specified, to support testing multiple jobs. | |
# | |
# def test_hello_and_logging_jobs | |
# assert_nothing_raised do | |
# expect_performed_jobs 2, only: [HelloJob, LoggingJob] do | |
# HelloJob.perform_later('jeremy') | |
# LoggingJob.perform_later('stewie') | |
# RescueJob.perform_later('david') | |
# end | |
# end | |
# end | |
# | |
# Note: This assertion is simply a shortcut for: | |
# | |
# expect_performed_jobs 0, &block | |
def expect_no_performed_jobs(only: nil, &block) | |
expect_performed_jobs 0, only: only, &block | |
end | |
# Asserts that the job passed in the block has been enqueued with the given arguments. | |
# | |
# def test_assert_enqueued_with | |
# assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low') do | |
# MyJob.perform_later(1,2,3) | |
# end | |
# | |
# assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon) do | |
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later | |
# end | |
# end | |
RSpec::Matchers.define :have_enqueued_job do |expected| | |
match do |actual| | |
actual == expected | |
end | |
failure_message do |actual| | |
"#{expected} jobs expected, but #{actual} were performed" | |
end | |
end | |
def assert_enqueued_with(args = {}) | |
original_enqueued_jobs_count = enqueued_jobs.count | |
args.assert_valid_keys(:job, :args, :at, :queue) | |
serialized_args = serialize_args_for_assertion(args) | |
yield | |
in_block_jobs = enqueued_jobs.drop(original_enqueued_jobs_count) | |
matching_job = in_block_jobs.find do |job| | |
serialized_args.all? { |key, value| value == job[key] } | |
end | |
assert matching_job, "No enqueued job found with #{args}" | |
instantiate_job(matching_job) | |
end | |
# Asserts that the job passed in the block has been performed with the given arguments. | |
# | |
# def test_assert_performed_with | |
# assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high') do | |
# MyJob.perform_later(1,2,3) | |
# end | |
# | |
# assert_performed_with(job: MyJob, at: Date.tomorrow.noon) do | |
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later | |
# end | |
# end | |
def assert_performed_with(args = {}) | |
original_performed_jobs_count = performed_jobs.count | |
args.assert_valid_keys(:job, :args, :at, :queue) | |
serialized_args = serialize_args_for_assertion(args) | |
perform_enqueued_jobs { yield } | |
in_block_jobs = performed_jobs.drop(original_performed_jobs_count) | |
matching_job = in_block_jobs.find do |job| | |
serialized_args.all? { |key, value| value == job[key] } | |
end | |
assert matching_job, "No performed job found with #{args}" | |
instantiate_job(matching_job) | |
end | |
def perform_enqueued_jobs(only: nil) | |
old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs | |
old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs | |
old_filter = queue_adapter.filter | |
begin | |
queue_adapter.perform_enqueued_jobs = true | |
queue_adapter.perform_enqueued_at_jobs = true | |
queue_adapter.filter = only | |
yield | |
ensure | |
queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs | |
queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs | |
queue_adapter.filter = old_filter | |
end | |
end | |
def queue_adapter | |
ActiveJob::Base.queue_adapter | |
end | |
delegate :enqueued_jobs, :enqueued_jobs=, | |
:performed_jobs, :performed_jobs=, | |
to: :queue_adapter | |
private | |
def clear_enqueued_jobs # :nodoc: | |
enqueued_jobs.clear | |
end | |
def clear_performed_jobs # :nodoc: | |
performed_jobs.clear | |
end | |
def enqueued_jobs_size(only: nil) # :nodoc: | |
if only | |
enqueued_jobs.count { |job| Array(only).include?(job.fetch(:job)) } | |
else | |
enqueued_jobs.count | |
end | |
end | |
def serialize_args_for_assertion(args) # :nodoc: | |
args.dup.tap do |serialized_args| | |
serialized_args[:args] = ActiveJob::Arguments.serialize(serialized_args[:args]) if serialized_args[:args] | |
serialized_args[:at] = serialized_args[:at].to_f if serialized_args[:at] | |
end | |
end | |
def instantiate_job(payload) # :nodoc: | |
job = payload[:job].new(*payload[:args]) | |
job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at) | |
job.queue_name = payload[:queue] | |
job | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment