Module: ActiveJob::TestHelper
- Includes:
- ActiveSupport::Testing::Assertions
- Included in:
- TestCase
- Defined in:
- lib/active_job/test_helper.rb
Overview
Provides helper methods for testing Active Job
Defined Under Namespace
Modules: TestQueueAdapter
Instance Method Summary collapse
-
#after_teardown ⇒ Object
:nodoc:.
-
#assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that the number of enqueued jobs matches the given number.
-
#assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) ⇒ Object
Asserts that the job has been enqueued with the given arguments.
-
#assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that no jobs have been enqueued.
-
#assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that no jobs have been performed.
-
#assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that the number of performed jobs matches the given number.
-
#assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) ⇒ Object
Asserts that the job has been performed with the given arguments.
-
#before_setup ⇒ Object
:nodoc:.
-
#perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block) ⇒ Object
Performs all enqueued jobs.
-
#queue_adapter ⇒ Object
Accesses the queue_adapter set by ActiveJob::Base.
-
#queue_adapter_for_test ⇒ Object
Returns a queue adapter instance to use with all Active Job test helpers.
Instance Method Details
#after_teardown ⇒ Object
:nodoc:
51 52 53 54 55 |
# File 'lib/active_job/test_helper.rb', line 51 def after_teardown # :nodoc: super queue_adapter_changed_jobs.each { |klass| klass.disable_test_adapter } end |
#assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that the number of enqueued jobs matches the given number.
def test_jobs
assert_enqueued_jobs 0
HelloJob.perform_later('david')
assert_enqueued_jobs 1
HelloJob.perform_later('abdelkader')
assert_enqueued_jobs 2
end
If a block is passed, asserts that the block will cause the specified number of jobs to be enqueued.
def test_jobs_again
assert_enqueued_jobs 1 do
HelloJob.perform_later('cristian')
end
assert_enqueued_jobs 2 do
HelloJob.perform_later('aaron')
HelloJob.perform_later('rafael')
end
end
Asserts the number of times a specific job was enqueued by passing :only
option.
def test_logging_job
assert_enqueued_jobs 1, only: LoggingJob do
LoggingJob.perform_later
HelloJob.perform_later('jeremy')
end
end
Asserts the number of times a job except specific class was enqueued by passing :except
option.
def test_logging_job
assert_enqueued_jobs 1, except: HelloJob do
LoggingJob.perform_later
HelloJob.perform_later('jeremy')
end
end
:only
and :except
options accept Class, Array of Class, or Proc. When passed a Proc, a hash containing the job’s class and it’s argument are passed as argument.
Asserts the number of times a job is enqueued to a specific queue by passing :queue
option.
def test_logging_job
assert_enqueued_jobs 2, queue: 'default' do
LoggingJob.perform_later
HelloJob.perform_later('elfassy')
end
end
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/active_job/test_helper.rb', line 118 def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block) if block_given? original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue) _assert_nothing_raised_or_warn("assert_enqueued_jobs", &block) new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue) actual_count = (new_jobs - original_jobs).count else actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count end assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued" end |
#assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) ⇒ Object
Asserts that the job has been enqueued with the given arguments.
def test_assert_enqueued_with
MyJob.perform_later(1,2,3)
assert_enqueued_with(job: MyJob, args: [1,2,3])
MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
end
For keyword arguments, specify them as a hash inside an array:
def test_assert_enqueued_with_keyword_arguments
MyJob.perform_later(arg1: 'value1', arg2: 'value2')
assert_enqueued_with(job: MyJob, args: [{ arg1: 'value1', arg2: 'value2' }])
end
The given arguments may also be specified as matcher procs that return a boolean value indicating whether a job’s attribute meets certain criteria.
For example, a proc can be used to match a range of times:
def test_assert_enqueued_with
at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
MyJob.set(wait_until: Date.today.noon).perform_later
assert_enqueued_with(job: MyJob, at: at_matcher)
end
A proc can also be used to match a subset of a job’s args:
def test_assert_enqueued_with
args_matcher = ->(job_args) { job_args[0].key?(:foo) }
MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
assert_enqueued_with(job: MyJob, args: args_matcher)
end
If a block is passed, asserts that the block will cause the job to be enqueued with the given arguments.
def test_assert_enqueued_with
assert_enqueued_with(job: MyJob, args: [1,2,3]) 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
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/active_job/test_helper.rb', line 394 def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact expected_args = prepare_args_for_assertion(expected) potential_matches = [] if block_given? original_enqueued_jobs = enqueued_jobs.dup _assert_nothing_raised_or_warn("assert_enqueued_with", &block) jobs = enqueued_jobs - original_enqueued_jobs else jobs = enqueued_jobs end matching_job = jobs.find do |enqueued_job| deserialized_job = deserialize_args_for_assertion(enqueued_job) potential_matches << deserialized_job expected_args.all? do |key, value| if value.respond_to?(:call) value.call(deserialized_job[key]) else value == deserialized_job[key] end end end matching_class = potential_matches.select do |enqueued_job| enqueued_job["job_class"] == job.to_s end = +"No enqueued job found with #{expected}" if potential_matches.empty? << "\n\nNo jobs were enqueued" elsif matching_class.empty? << "\n\nNo jobs of class #{expected[:job]} were enqueued, job classes enqueued: " << potential_matches.map { |job| job["job_class"] }.join(", ") else << "\n\nPotential matches: #{matching_class.join("\n")}" end assert matching_job, instantiate_job(matching_job) end |
#assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that no jobs have been enqueued.
def test_jobs
assert_no_enqueued_jobs
HelloJob.perform_later('jeremy')
assert_enqueued_jobs 1
end
If a block is passed, asserts that the block will not cause any job to be enqueued.
def test_jobs_again
assert_no_enqueued_jobs do
# No job should be enqueued from this block
end
end
Asserts that no jobs of a specific kind are enqueued by passing :only
option.
def test_no_logging
assert_no_enqueued_jobs only: LoggingJob do
HelloJob.perform_later('jeremy')
end
end
Asserts that no jobs except specific class are enqueued by passing :except
option.
def test_no_logging
assert_no_enqueued_jobs except: HelloJob do
HelloJob.perform_later('jeremy')
end
end
:only
and :except
options accept Class, Array of Class, or Proc. When passed a Proc, a hash containing the job’s class and it’s argument are passed as argument.
Asserts that no jobs are enqueued to a specific queue by passing :queue
option
def test_no_logging
assert_no_enqueued_jobs queue: 'default' do
LoggingJob.set(queue: :some_queue).perform_later
end
end
Note: This assertion is simply a shortcut for:
assert_enqueued_jobs 0, &block
180 181 182 |
# File 'lib/active_job/test_helper.rb', line 180 def assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block) assert_enqueued_jobs 0, only: only, except: except, queue: queue, &block end |
#assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that no jobs have been performed.
def test_jobs
assert_no_performed_jobs
perform_enqueued_jobs do
HelloJob.perform_later('matthew')
assert_performed_jobs 1
end
end
If a block is passed, asserts that the block will not cause any job to be performed.
def test_jobs_again
assert_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 not be performed.
def test_no_logging
assert_no_performed_jobs only: LoggingJob do
HelloJob.perform_later('jeremy')
end
end
Also if the :except
option is specified, then the job(s) except specific class will not be performed.
def test_no_logging
assert_no_performed_jobs except: HelloJob do
HelloJob.perform_later('jeremy')
end
end
:only
and :except
options accept Class, Array of Class, or Proc. When passed a Proc, an instance of the job will be passed as argument.
If the :queue
option is specified, then only the job(s) enqueued to a specific queue will not be performed.
def test_assert_no_performed_jobs_with_queue_option
assert_no_performed_jobs queue: :some_queue do
HelloJob.set(queue: :other_queue).perform_later("jeremy")
end
end
Note: This assertion is simply a shortcut for:
assert_performed_jobs 0, &block
338 339 340 |
# File 'lib/active_job/test_helper.rb', line 338 def assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block) assert_performed_jobs 0, only: only, except: except, queue: queue, &block end |
#assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block) ⇒ Object
Asserts that the number of performed jobs matches the given number. If no block is passed, perform_enqueued_jobs
must be called around or after the job call.
def test_jobs
assert_performed_jobs 0
perform_enqueued_jobs do
HelloJob.perform_later('xavier')
end
assert_performed_jobs 1
HelloJob.perform_later('yves')
perform_enqueued_jobs
assert_performed_jobs 2
end
If a block is passed, asserts that the block will cause the specified number of jobs to be performed.
def test_jobs_again
assert_performed_jobs 1 do
HelloJob.perform_later('robin')
end
assert_performed_jobs 2 do
HelloJob.perform_later('carlos')
HelloJob.perform_later('sean')
end
end
This method also supports filtering. If the :only
option is specified, then only the listed job(s) will be performed.
def test_hello_job
assert_performed_jobs 1, only: HelloJob do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later
end
end
Also if the :except
option is specified, then the job(s) except specific class will be performed.
def test_hello_job
assert_performed_jobs 1, except: LoggingJob 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
assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later('stewie')
RescueJob.perform_later('david')
end
end
end
A proc may also be specified. When passed a Proc, the job’s instance will be passed as argument.
def test_hello_and_logging_jobs
assert_nothing_raised do
assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
HelloJob.perform_later('jeremy')
LoggingJob.perform_later('stewie')
RescueJob.perform_later('david')
end
end
end
If the :queue
option is specified, then only the job(s) enqueued to a specific queue will be performed.
def test_assert_performed_jobs_with_queue_option
assert_performed_jobs 1, queue: :some_queue do
HelloJob.set(queue: :some_queue).perform_later("jeremy")
HelloJob.set(queue: :other_queue).perform_later("bogdan")
end
end
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/active_job/test_helper.rb', line 270 def assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block) if block_given? original_count = performed_jobs.size perform_enqueued_jobs(only: only, except: except, queue: queue, &block) new_count = performed_jobs.size performed_jobs_size = new_count - original_count else performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count end assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed" end |
#assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) ⇒ Object
Asserts that the job has been performed with the given arguments.
def test_assert_performed_with
MyJob.perform_later(1,2,3)
perform_enqueued_jobs
assert_performed_with(job: MyJob, args: [1,2,3])
MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
perform_enqueued_jobs
assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
end
The given arguments may also be specified as matcher procs that return a boolean value indicating whether a job’s attribute meets certain criteria.
For example, a proc can be used to match a range of times:
def test_assert_performed_with
at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
MyJob.set(wait_until: Date.today.noon).perform_later
perform_enqueued_jobs
assert_performed_with(job: MyJob, at: at_matcher)
end
A proc can also be used to match a subset of a job’s args:
def test_assert_performed_with
args_matcher = ->(job_args) { job_args[0].key?(:foo) }
MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
perform_enqueued_jobs
assert_performed_with(job: MyJob, args: args_matcher)
end
If a block is passed, that block performs all of the jobs that were enqueued throughout the duration of the block and asserts that the job has been performed with the given arguments in the block.
def test_assert_performed_with
assert_performed_with(job: MyJob, args: [1,2,3]) 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
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
# File 'lib/active_job/test_helper.rb', line 496 def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact expected_args = prepare_args_for_assertion(expected) potential_matches = [] if block_given? original_performed_jobs_count = performed_jobs.count perform_enqueued_jobs(&block) jobs = performed_jobs.drop(original_performed_jobs_count) else jobs = performed_jobs end matching_job = jobs.find do |enqueued_job| deserialized_job = deserialize_args_for_assertion(enqueued_job) potential_matches << deserialized_job expected_args.all? do |key, value| if value.respond_to?(:call) value.call(deserialized_job[key]) else value == deserialized_job[key] end end end matching_class = potential_matches.select do |enqueued_job| enqueued_job["job_class"] == job.to_s end = +"No performed job found with #{expected}" if potential_matches.empty? << "\n\nNo jobs were performed" elsif matching_class.empty? << "\n\nNo jobs of class #{expected[:job]} were performed, job classes performed: " << potential_matches.map { |job| job["job_class"] }.join(", ") else << "\n\nPotential matches: #{matching_class.join("\n")}" end assert matching_job, instantiate_job(matching_job) end |
#before_setup ⇒ Object
:nodoc:
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/active_job/test_helper.rb', line 39 def before_setup # :nodoc: test_adapter = queue_adapter_for_test queue_adapter_changed_jobs.each do |klass| klass.enable_test_adapter(test_adapter) end clear_enqueued_jobs clear_performed_jobs super end |
#perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block) ⇒ Object
Performs all enqueued jobs. If a block is given, performs all of the jobs that were enqueued throughout the duration of the block. If a block is not given, performs all of the enqueued jobs up to this point in the test.
def test_perform_enqueued_jobs
perform_enqueued_jobs do
MyJob.perform_later(1, 2, 3)
end
assert_performed_jobs 1
end
def test_perform_enqueued_jobs_without_block
MyJob.perform_later(1, 2, 3)
perform_enqueued_jobs
assert_performed_jobs 1
end
This method also supports filtering. If the :only
option is specified, then only the listed job(s) will be performed.
def test_perform_enqueued_jobs_with_only
perform_enqueued_jobs(only: MyJob) do
MyJob.perform_later(1, 2, 3) # will be performed
HelloJob.perform_later(1, 2, 3) # will not be performed
end
assert_performed_jobs 1
end
Also if the :except
option is specified, then the job(s) except specific class will be performed.
def test_perform_enqueued_jobs_with_except
perform_enqueued_jobs(except: HelloJob) do
MyJob.perform_later(1, 2, 3) # will be performed
HelloJob.perform_later(1, 2, 3) # will not be performed
end
assert_performed_jobs 1
end
:only
and :except
options accept Class, Array of Class, or Proc. When passed a Proc, an instance of the job will be passed as argument.
If the :queue
option is specified, then only the job(s) enqueued to a specific queue will be performed.
def test_perform_enqueued_jobs_with_queue
perform_enqueued_jobs queue: :some_queue do
MyJob.set(queue: :some_queue).perform_later(1, 2, 3) # will be performed
HelloJob.set(queue: :other_queue).perform_later(1, 2, 3) # will not be performed
end
assert_performed_jobs 1
end
If the :at
option is specified, then only jobs that have been enqueued to run at or before the given time will be performed. This includes jobs that have been enqueued without a time.
If queue_adapter_for_test is overridden to return a different adapter, perform_enqueued_jobs
will merely execute the block.
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
# File 'lib/active_job/test_helper.rb', line 604 def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block) return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given? return _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block) unless using_test_adapter? validate_option(only: only, except: except) 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 old_reject = queue_adapter.reject old_queue = queue_adapter.queue old_at = queue_adapter.at begin queue_adapter.perform_enqueued_jobs = true queue_adapter.perform_enqueued_at_jobs = true queue_adapter.filter = only queue_adapter.reject = except queue_adapter.queue = queue queue_adapter.at = at _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block) 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 queue_adapter.reject = old_reject queue_adapter.queue = old_queue queue_adapter.at = old_at end end |
#queue_adapter ⇒ Object
Accesses the queue_adapter set by ActiveJob::Base.
def test_assert_job_has_custom_queue_adapter_set
assert_instance_of CustomQueueAdapter, HelloJob.queue_adapter
end
642 643 644 |
# File 'lib/active_job/test_helper.rb', line 642 def queue_adapter ActiveJob::Base.queue_adapter end |
#queue_adapter_for_test ⇒ Object
Returns a queue adapter instance to use with all Active Job test helpers. By default, returns an instance of ActiveJob::QueueAdapters::TestAdapter. Override this method to specify a different adapter. The adapter must implement the same interface as ActiveJob::QueueAdapters::TestAdapter.
61 62 63 |
# File 'lib/active_job/test_helper.rb', line 61 def queue_adapter_for_test ActiveJob::QueueAdapters::TestAdapter.new end |