Update job testing guidelines

The current example test for jobs using `perform_now` to run the job inline. This is problematic for jobs that have retries configured, as any exception that is retried will be silently rescued. Ideally, the test will still fail because the job did not perform the work it was supposed to, but it makes finding the root cause a lot harder.

Testing with `perform_enqueued_jobs` and `perform_later` gets around this problem, as the retries are also performed immediately and, assuming that the exception happens consistently, it will bubble up after exhausting its retries.

Therefore, this PR updates the basic test guidance to suggest `perform_enqueued_jobs` and `perform_later` over `perform_now`.

Both described behaviours make it harder to test that a job raises a specific exception, so this requires special handling, which I added a paragraph on. I can pull that out to a separate PR if desired.
This commit is contained in:
Sander Verdonschot 2023-08-16 16:49:46 -04:00 committed by GitHub
parent 5cf742ef51
commit 315db730cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 23 additions and 2 deletions

View File

@ -1929,13 +1929,15 @@ require "test_helper"
class BillingJobTest < ActiveJob::TestCase
test "that account is charged" do
BillingJob.perform_now(account, product)
perform_enqueued_jobs do
BillingJob.perform_later(account, product)
end
assert account.reload.charged_for?(product)
end
end
```
This test is pretty simple and only asserts that the job did work that was expected.
This test is pretty simple and only asserts that the job did work that was expected. You can also use `perform_now` to run the job inline, but if you have retries configured, any exceptions raised by the job will be silently ignored, whereas `perform_enqueued_jobs` will fail the test and print the exception information.
### Custom Assertions and Testing Jobs inside Other Components
@ -1982,6 +1984,25 @@ end
All previously performed and enqueued jobs are cleared before any test runs,
so you can safely assume that no jobs have already been executed in the scope of each test.
### Testing that Exceptions are Raised
Testing that your job raises an exception in certain cases can be tricky, especially when you have retries configured. The `perform_enqueued_jobs` helper fails any test where a job raises an exception, so to have the test succeed when the exception is raised you have call the job's `perform` method directly.
```ruby
require "test_helper"
class BillingJobTest < ActiveJob::TestCase
test "does not charge accounts with insufficient funds" do
assert_raises(InsufficientFundsError) do
BillingJob.new(empty_account, product).perform
end
refute account.reload.charged_for?(product)
end
end
```
This method is not recommended in general, as it circumvents some parts of the framework, such as argument serialization.
Testing Action Cable
--------------------