rspec-sidekiq 3.0.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGES.md +61 -0
- data/LICENSE +12 -0
- data/README.md +270 -94
- data/lib/rspec/sidekiq/batch.rb +34 -4
- data/lib/rspec/sidekiq/configuration.rb +29 -2
- data/lib/rspec/sidekiq/helpers/within_sidekiq_retries_exhausted_block.rb +5 -3
- data/lib/rspec/sidekiq/helpers.rb +2 -0
- data/lib/rspec/sidekiq/matchers/base.rb +368 -0
- data/lib/rspec/sidekiq/matchers/be_delayed.rb +19 -3
- data/lib/rspec/sidekiq/matchers/be_expired_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_processed_in.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_retryable.rb +2 -0
- data/lib/rspec/sidekiq/matchers/be_unique.rb +23 -1
- data/lib/rspec/sidekiq/matchers/enqueue_sidekiq_job.rb +91 -0
- data/lib/rspec/sidekiq/matchers/have_enqueued_sidekiq_job.rb +35 -0
- data/lib/rspec/sidekiq/matchers/save_backtrace.rb +2 -0
- data/lib/rspec/sidekiq/matchers.rb +16 -8
- data/lib/rspec/sidekiq/sidekiq.rb +3 -1
- data/lib/rspec/sidekiq/version.rb +3 -1
- data/lib/rspec-sidekiq.rb +4 -0
- metadata +146 -84
- data/.gitattributes +0 -22
- data/.gitignore +0 -2
- data/.rspec +0 -4
- data/.simplecov +0 -5
- data/Gemfile +0 -9
- data/lib/rspec/sidekiq/matchers/have_enqueued_job.rb +0 -183
- data/rspec-sidekiq.gemspec +0 -37
- data/spec/rspec/sidekiq/batch_spec.rb +0 -77
- data/spec/rspec/sidekiq/helpers/retries_exhausted_spec.rb +0 -40
- data/spec/rspec/sidekiq/matchers/be_delayed_spec.rb +0 -238
- data/spec/rspec/sidekiq/matchers/be_expired_in_spec.rb +0 -57
- data/spec/rspec/sidekiq/matchers/be_processed_in_spec.rb +0 -114
- data/spec/rspec/sidekiq/matchers/be_retryable_spec.rb +0 -129
- data/spec/rspec/sidekiq/matchers/be_unique_spec.rb +0 -115
- data/spec/rspec/sidekiq/matchers/have_enqueued_job_spec.rb +0 -228
- data/spec/rspec/sidekiq/matchers/save_backtrace_spec.rb +0 -136
- data/spec/rspec/sidekiq/sidekiq_spec.rb +0 -15
- data/spec/spec_helper.rb +0 -29
- data/spec/support/factories.rb +0 -33
- data/spec/support/init.rb +0 -6
- data/spec/support/test_action_mailer.rb +0 -6
- data/spec/support/test_job.rb +0 -6
- data/spec/support/test_resource.rb +0 -16
- data/spec/support/test_worker.rb +0 -8
- data/spec/support/test_worker_alternative.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 56ce84afbf67491fa24da1f527bced61c54afa3d62dbb50e6a09a89e8c0bc16c
|
4
|
+
data.tar.gz: 5b4a368bbb098d580713009fb9381d66326c37eced31c91eaf85b43158a85db5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ec18b3d6ceff7390807d7358259b44f236ca6d81b1b9175c069b6c4912041b914082042a5396c7cf1eb0b602a5448d9aacd9e23b3cee211ad7222c3ec3719af
|
7
|
+
data.tar.gz: 4f0232e7b482f7c565a5cca98be9b7143e51adbe6015329f9d052e393fd857fe97e2449fb53f9e3d209ff6319c54e23e9e2919e7003a44bfc00834692039eed0
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,64 @@
|
|
1
|
+
Unreleased
|
2
|
+
---
|
3
|
+
* Add `until` matcher for Sidekiq Enterprise unique jobs (#232, #147)
|
4
|
+
* Add `with_context` matcher for matching against job contexts (#222)
|
5
|
+
* Support for Sidekiq 8 (#233)
|
6
|
+
* Add `frozen_string_literal: true` (#220)
|
7
|
+
* Fix queue always nil in default_retries_exhausted_message (#229)
|
8
|
+
* Fix pattern matching warnings on Ruby 2.7 (#227)
|
9
|
+
|
10
|
+
5.0.0
|
11
|
+
---
|
12
|
+
* [BREAKING] Make `have_enqueued_sidekiq_job()` match jobs with any arguments (same as `enqueue_sidekiq_job()` or `have_enqueued_sidekiq_job(any_args)`) (#215)
|
13
|
+
* Add support for expected number of jobs to both `enqueue_sidekiq_job` and `have_enqueued_sidekiq_job` (#219)
|
14
|
+
|
15
|
+
4.2.0
|
16
|
+
---
|
17
|
+
* Add warning about `have_enqueued_sidekiq_job` with no arguments (default will change in next major release) (#216, #217)
|
18
|
+
|
19
|
+
4.1.0
|
20
|
+
---
|
21
|
+
* Add Composable support to `enqueue_sidekiq_job` and
|
22
|
+
`have_enqueued_sidekiq_job` (#211)
|
23
|
+
* Add `immediately` to specify that a job should be enqueued without any delay (#210)
|
24
|
+
|
25
|
+
4.0.2
|
26
|
+
---
|
27
|
+
* Explicitly require forwardable (#204)
|
28
|
+
|
29
|
+
4.0.1
|
30
|
+
---
|
31
|
+
* Restore the old normalizing expected args behavior with symbols (#205)
|
32
|
+
* fixes an unintentional breaking change in 4.0.0
|
33
|
+
|
34
|
+
4.0.0
|
35
|
+
---
|
36
|
+
* [BREAKING] Dropped support for matching jobs on ActiveJob's private API args, (e.g. `_aj_globalid` and `_aj_ruby2_keywords`). `_aj_globalid` can be replaced with the object itself, e.g. `have_enqueued_sidekiq_job(user)`.
|
37
|
+
* [BREAKING] Dropped support for Ruby 2.6
|
38
|
+
* [BREAKING] Mocking Sidekiq::Batch is now _opt in_ (was opt-out) by default
|
39
|
+
* [BREAKING] Dropped the `have_enqueued_job` matcher (deprecated since v3)
|
40
|
+
* [BREAKING] Dropped support for Sidekiq <5
|
41
|
+
* [BREAKING] Dropped support for Rails 5
|
42
|
+
* Add support for Sidekiq 7 (#192)
|
43
|
+
* Add support for builtin argument matchers from rspec mocks for
|
44
|
+
`have_enqueued_sidekiq_job` (#200)
|
45
|
+
* Add `#on` to `have_enqueued_sidekiq_job` to support testing queue at enqueue time (#197)
|
46
|
+
* Add `enqueue_sidekiq_job` for block-syntax style expectations
|
47
|
+
* Clarified `have_enqueued_sidekiq_job` error message to make it clear that the "actual arguments" list is an array of argument-lists across all enqueued jobs. (#195)
|
48
|
+
* Fix `in` and `at` evaluation to match Sidekiq (#194)
|
49
|
+
* Fix `be_delayed` argument matcher (#196)
|
50
|
+
* Fix argument matching ignoring order (#200)
|
51
|
+
* Fix `be_delayed` time math when using `delay_for` (#198)
|
52
|
+
|
53
|
+
3.1.0
|
54
|
+
---
|
55
|
+
* Add support for latest ruby and Rails 5 (coding-bunny #156)
|
56
|
+
* Support `Class#method` notation in batch callback (caalberts #155)
|
57
|
+
* Fix bug with time comparison in delayed jobs (geeosh #153 with help from col)
|
58
|
+
* remove usage of `Integer#blank?` (lanej #152)
|
59
|
+
* Add `NullBatch#description` (dsantosmerino #139)
|
60
|
+
* README updates (BenMusch #142, akihikodaki #141, wpolicarpo #160)
|
61
|
+
|
1
62
|
3.0.3
|
2
63
|
---
|
3
64
|
* Re-splat arguments for the have_enqueued_job alias (aprescott #136)
|
data/LICENSE
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
+
Copyright (c) 2023 Will Spurgin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
10
|
+
|
11
|
+
Elements of this software and associated documentation files are covered by the following license:
|
12
|
+
|
13
|
+
The MIT License (MIT)
|
14
|
+
|
3
15
|
Copyright (c) 2014, 2015 Phil Ostler
|
4
16
|
|
5
17
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
data/README.md
CHANGED
@@ -1,23 +1,7 @@
|
|
1
|
-
|
1
|
+
[](https://badge.fury.io/rb/rspec-sidekiq)
|
2
|
+
[![Github Actions CI][github_actions_badge]][github_actions]
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
[![RubyGems][gem_version_badge]][ruby_gems]
|
6
|
-
[![Code Climate][code_climate_badge]][code_climate]
|
7
|
-
[![Travis CI][travis_ci_badge]][travis_ci]
|
8
|
-
[![Coveralls][coveralls_badge]][coveralls]
|
9
|
-
[![Gemnasium][gemnasium_badge]][gemnasium]
|
10
|
-
|
11
|
-
***Simple testing of Sidekiq jobs via a collection of matchers and helpers***
|
12
|
-
|
13
|
-
[RubyGems][ruby_gems] |
|
14
|
-
[Code Climate][code_climate] |
|
15
|
-
[GitHub][github] |
|
16
|
-
[Travis CI][travis_ci] |
|
17
|
-
[Coveralls][coveralls] |
|
18
|
-
[Gemnasium][gemnasium] |
|
19
|
-
[RubyDoc][ruby_doc] |
|
20
|
-
[Ruby Toolbox][ruby_toolbox]
|
4
|
+
Simple testing of Sidekiq jobs via a collection of matchers and helpers.
|
21
5
|
|
22
6
|
[Jump to Matchers »](#matchers) | [Jump to Helpers »](#helpers)
|
23
7
|
|
@@ -48,36 +32,184 @@ end
|
|
48
32
|
```
|
49
33
|
|
50
34
|
## Matchers
|
51
|
-
* [
|
52
|
-
* [
|
53
|
-
* [
|
54
|
-
* [
|
55
|
-
* [
|
35
|
+
* [```enqueue_sidekiq_job```](#enqueue_sidekiq_job)
|
36
|
+
* [```have_enqueued_sidekiq_job```](#have_enqueued_sidekiq_job)
|
37
|
+
* [```be_processed_in```](#be_processed_in)
|
38
|
+
* [```be_retryable```](#be_retryable)
|
39
|
+
* [```save_backtrace```](#save_backtrace)
|
40
|
+
* [```be_unique```](#be_unique)
|
41
|
+
* [```be_expired_in```](#be_expired_in)
|
42
|
+
* [```be_delayed``` (_deprecated_)](#be_delayed)
|
43
|
+
|
44
|
+
### ```enqueue_sidekiq_job```
|
45
|
+
|
46
|
+
*Describes that the block should enqueue a job*. Optionally specify the
|
47
|
+
specific job class, arguments, timing, and other context
|
56
48
|
|
57
|
-
### be_delayed
|
58
|
-
*Describes a method that should be invoked asynchronously (See [Sidekiq Delayed Extensions][sidekiq_wiki_delayed_extensions])*
|
59
49
|
```ruby
|
60
|
-
|
61
|
-
expect
|
62
|
-
Object.delay.is_a? Object # delay with argument
|
63
|
-
expect(Object.method :is_a?).to be_delayed(Object)
|
50
|
+
# Basic
|
51
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job
|
64
52
|
|
65
|
-
|
66
|
-
expect
|
67
|
-
Object.delay_for(1.hour).is_a? Object # delay for with argument
|
68
|
-
expect(Object.method :is_a?).to be_delayed(Object).for 1.hour
|
53
|
+
# A specific job class
|
54
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job(AwesomeJob)
|
69
55
|
|
70
|
-
|
71
|
-
expect
|
72
|
-
Object.delay_until(1.hour.from_now).is_a? Object # delay until with argument
|
73
|
-
expect(Object.method :is_a?).to be_delayed(Object).until 1.hour.from_now
|
56
|
+
# with specific arguments
|
57
|
+
expect { AwesomeJob.perform_async "Awesome!" }.to enqueue_sidekiq_job.with("Awesome!")
|
74
58
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
59
|
+
# On a specific queue
|
60
|
+
expect { AwesomeJob.set(queue: "high").perform_async }.to enqueue_sidekiq_job.on("high")
|
61
|
+
|
62
|
+
# At a specific datetime
|
63
|
+
specific_time = 1.hour.from_now
|
64
|
+
expect { AwesomeJob.perform_at(specific_time) }.to enqueue_sidekiq_job.at(specific_time)
|
65
|
+
|
66
|
+
# In a specific interval (be mindful of freezing or managing time here)
|
67
|
+
freeze_time do
|
68
|
+
expect { AwesomeJob.perform_in(1.hour) }.to enqueue_sidekiq_job.in(1.hour)
|
69
|
+
end
|
70
|
+
|
71
|
+
# A specific number of times
|
72
|
+
|
73
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.once
|
74
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(1).time
|
75
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.exactly(:once)
|
76
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(1).time
|
77
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_least(:once)
|
78
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(2).times
|
79
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:twice)
|
80
|
+
expect { AwesomeJob.perform_async }.to enqueue_sidekiq_job.at_most(:thrice)
|
81
|
+
|
82
|
+
# With specific context:
|
83
|
+
# Useful for testing anything `set` on the job, including
|
84
|
+
# overrides to things like `retry`
|
85
|
+
expect {
|
86
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
87
|
+
}.to enqueue_sidekiq_job.with_context(trace_id: anything)
|
88
|
+
|
89
|
+
expect {
|
90
|
+
AwesomeJob.set(retry: 5).perform_async
|
91
|
+
}.to enqueue_sidekiq_job.with_context(retry: 5)
|
92
|
+
|
93
|
+
# Combine and chain them as desired
|
94
|
+
expect { AwesomeJob.perform_at(specific_time, "Awesome!") }.to(
|
95
|
+
enqueue_sidekiq_job(AwesomeJob)
|
96
|
+
.with("Awesome!")
|
97
|
+
.on("default")
|
98
|
+
.at(specific_time)
|
99
|
+
)
|
100
|
+
|
101
|
+
# Also composable
|
102
|
+
expect do
|
103
|
+
AwesomeJob.perform_async
|
104
|
+
OtherJob.perform_async
|
105
|
+
end.to enqueue_sidekiq_job(AwesomeJob).and enqueue_sidekiq_job(OtherJob)
|
106
|
+
```
|
107
|
+
|
108
|
+
### ```have_enqueued_sidekiq_job```
|
109
|
+
|
110
|
+
Describes that there should be an enqueued job (with the specified arguments):
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
AwesomeJob.perform_async 'Awesome', true
|
114
|
+
# test with...
|
115
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job
|
116
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true)
|
117
|
+
```
|
118
|
+
|
119
|
+
You can use the built-in RSpec args matchers too:
|
120
|
+
```ruby
|
121
|
+
AwesomeJob.perform_async({"something" => "Awesome", "extra" => "stuff"})
|
122
|
+
|
123
|
+
# using built-in matchers from rspec-mocks:
|
124
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_including("something" => "Awesome"))
|
125
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job(any_args)
|
126
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job(hash_excluding("bad_stuff" => anything))
|
127
|
+
|
128
|
+
# composable as well
|
129
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job(any_args).and have_enqueued_sidekiq_job(hash_including("something" => "Awesome"))
|
130
|
+
```
|
131
|
+
|
132
|
+
You can specify the number of jobs enqueued:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.once
|
136
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(1).time
|
137
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.exactly(:once)
|
138
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(1).time
|
139
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_least(:once)
|
140
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(2).times
|
141
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:twice)
|
142
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.at_most(:thrice)
|
143
|
+
```
|
144
|
+
|
145
|
+
Likewise, specify what should be in the context:
|
146
|
+
```ruby
|
147
|
+
AwesomeJob.set(trace_id: "something").perform_async
|
148
|
+
|
149
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job.with_context(trace_id: anything)
|
150
|
+
```
|
151
|
+
|
152
|
+
#### Testing scheduled jobs
|
153
|
+
|
154
|
+
*Use chainable matchers `#at`, `#in` and `#immediately`*
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
time = 5.minutes.from_now
|
158
|
+
AwesomeJob.perform_at time, 'Awesome', true
|
159
|
+
# test with...
|
160
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true).at(time)
|
161
|
+
```
|
162
|
+
```ruby
|
163
|
+
AwesomeJob.perform_in 5.minutes, 'Awesome', true
|
164
|
+
# test with...
|
165
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true).in(5.minutes)
|
166
|
+
```
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
# Job scheduled for a date in the past are enqueued immediately.
|
170
|
+
AwesomeJob.perform_later 5.minutes.ago, 'Awesome', true # equivalent to: AwesomeJob.perform_async 'Awesome', true
|
171
|
+
# test with...
|
172
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true).immediately
|
78
173
|
```
|
79
174
|
|
80
|
-
|
175
|
+
#### Testing queue set for job
|
176
|
+
|
177
|
+
Use the chainable `#on` matcher
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
class AwesomeJob
|
181
|
+
include Sidekiq::Job
|
182
|
+
|
183
|
+
sidekiq_options queue: :low
|
184
|
+
end
|
185
|
+
|
186
|
+
AwesomeJob.perform_async("a little awesome")
|
187
|
+
|
188
|
+
# test with..
|
189
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job("a little awesome").on("low")
|
190
|
+
|
191
|
+
# Setting the queue when enqueuing
|
192
|
+
AwesomeJob.set(queue: "high").perform_async("Very Awesome!")
|
193
|
+
|
194
|
+
expect(AwesomeJob).to have_enqueued_sidekiq_job("Very Awesome!").on("high")
|
195
|
+
```
|
196
|
+
|
197
|
+
#### Testing ActiveMailer jobs
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
user = User.first
|
201
|
+
AwesomeActionMailer.invite(user, true).deliver_later
|
202
|
+
|
203
|
+
expect(Sidekiq::Worker).to have_enqueued_sidekiq_job(
|
204
|
+
"AwesomeActionMailer",
|
205
|
+
"invite",
|
206
|
+
"deliver_now",
|
207
|
+
user,
|
208
|
+
true
|
209
|
+
)
|
210
|
+
```
|
211
|
+
|
212
|
+
### ```be_processed_in```
|
81
213
|
*Describes the queue that a job should be processed in*
|
82
214
|
```ruby
|
83
215
|
sidekiq_options queue: :download
|
@@ -86,8 +218,12 @@ expect(AwesomeJob).to be_processed_in :download # or
|
|
86
218
|
it { is_expected.to be_processed_in :download }
|
87
219
|
```
|
88
220
|
|
89
|
-
### be_retryable
|
90
|
-
*Describes if a job should retry when there is a failure in
|
221
|
+
### ```be_retryable```
|
222
|
+
*Describes if a job should retry when there is a failure in its execution*
|
223
|
+
|
224
|
+
Note: this only tests against the `retry` option in the job's Sidekiq options.
|
225
|
+
To test an enqueued job's retry, i.e. `AwesomeJob.set(retry: 5)`, use
|
226
|
+
`with_context`
|
91
227
|
```ruby
|
92
228
|
sidekiq_options retry: 5
|
93
229
|
# test with...
|
@@ -101,14 +237,14 @@ expect(AwesomeJob).to be_retryable false # or
|
|
101
237
|
it { is_expected.to be_retryable false }
|
102
238
|
```
|
103
239
|
|
104
|
-
### save_backtrace
|
105
|
-
*Describes if a job should save the error backtrace when there is a failure in
|
240
|
+
### ```save_backtrace```
|
241
|
+
*Describes if a job should save the error backtrace when there is a failure in its execution*
|
106
242
|
```ruby
|
107
243
|
sidekiq_options backtrace: 5
|
108
244
|
# test with...
|
109
245
|
expect(AwesomeJob).to save_backtrace # or
|
110
246
|
it { is_expected.to save_backtrace }
|
111
|
-
# ...or alternatively
|
247
|
+
# ...or alternatively specify the number of lines that should be saved
|
112
248
|
expect(AwesomeJob).to save_backtrace 5 # or
|
113
249
|
it { is_expected.to save_backtrace 5 }
|
114
250
|
# ...or when it should not save the backtrace
|
@@ -118,16 +254,35 @@ it { is_expected.to_not save_backtrace } # or
|
|
118
254
|
it { is_expected.to save_backtrace false }
|
119
255
|
```
|
120
256
|
|
121
|
-
### be_unique
|
122
|
-
|
257
|
+
### ```be_unique```
|
258
|
+
|
259
|
+
:warning: This is intended to for Sidekiq Enterprise unique job implementation.
|
260
|
+
There is _limited_ support for Sidekiq Unique Jobs, but compatibility is not
|
261
|
+
guaranteed.
|
262
|
+
|
263
|
+
*Describes when a job should be unique within its queue*
|
123
264
|
```ruby
|
124
|
-
sidekiq_options
|
265
|
+
sidekiq_options unique_for: 1.hour
|
125
266
|
# test with...
|
126
267
|
expect(AwesomeJob).to be_unique
|
127
268
|
it { is_expected.to be_unique }
|
269
|
+
|
270
|
+
# specify a specific interval
|
271
|
+
sidekiq_options unique_for: 1.hour
|
272
|
+
it { is_expected.to be_unique.for(1.hour) }
|
128
273
|
```
|
129
274
|
|
130
|
-
|
275
|
+
#### `until` sub-matcher
|
276
|
+
|
277
|
+
:warning: This sub-matcher only works for Sidekiq Enterprise
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
sidekiq_options unique_for: 1.hour, unique_until: :start
|
281
|
+
it { is_expected.to be_unique.until(:start) }
|
282
|
+
```
|
283
|
+
|
284
|
+
|
285
|
+
### ```be_expired_in```
|
131
286
|
*Describes when a job should expire*
|
132
287
|
```ruby
|
133
288
|
sidekiq_options expires_in: 1.hour
|
@@ -136,33 +291,32 @@ it { is_expected.to be_expired_in 1.hour }
|
|
136
291
|
it { is_expected.to_not be_expired_in 2.hours }
|
137
292
|
```
|
138
293
|
|
139
|
-
###
|
140
|
-
*Describes that there should be an enqueued job with the specified arguments*
|
294
|
+
### ```be_delayed```
|
141
295
|
|
142
|
-
**
|
143
|
-
|
296
|
+
**This matcher is deprecated**. Use of it with Sidekiq 7+ will raise an error.
|
297
|
+
Sidekiq 7 [dropped Delayed
|
298
|
+
Extensions](https://github.com/sidekiq/sidekiq/issues/5076).
|
144
299
|
|
300
|
+
*Describes a method that should be invoked asynchronously (See [Sidekiq Delayed Extensions][sidekiq_wiki_delayed_extensions])*
|
145
301
|
```ruby
|
146
|
-
|
147
|
-
|
148
|
-
|
302
|
+
Object.delay.is_nil? # delay
|
303
|
+
expect(Object.method :is_nil?).to be_delayed
|
304
|
+
Object.delay.is_a? Object # delay with argument
|
305
|
+
expect(Object.method :is_a?).to be_delayed(Object)
|
149
306
|
|
150
|
-
#
|
151
|
-
|
152
|
-
|
153
|
-
|
307
|
+
Object.delay_for(1.hour).is_nil? # delay for
|
308
|
+
expect(Object.method :is_nil?).to be_delayed.for 1.hour
|
309
|
+
Object.delay_for(1.hour).is_a? Object # delay for with argument
|
310
|
+
expect(Object.method :is_a?).to be_delayed(Object).for 1.hour
|
154
311
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
Awesomejob.perform_in 5.minutes, 'Awesome', true
|
164
|
-
# test with...
|
165
|
-
expect(AwesomeJob).to have_enqueued_sidekiq_job('Awesome', true).in(5.minutes)
|
312
|
+
Object.delay_until(1.hour.from_now).is_nil? # delay until
|
313
|
+
expect(Object.method :is_nil?).to be_delayed.until 1.hour.from_now
|
314
|
+
Object.delay_until(1.hour.from_now).is_a? Object # delay until with argument
|
315
|
+
expect(Object.method :is_a?).to be_delayed(Object).until 1.hour.from_now
|
316
|
+
|
317
|
+
#Rails Mailer
|
318
|
+
MyMailer.delay.some_mail
|
319
|
+
expect(MyMailer.instance_method :some_mail).to be_delayed
|
166
320
|
```
|
167
321
|
|
168
322
|
## Example matcher usage
|
@@ -184,11 +338,38 @@ end
|
|
184
338
|
```
|
185
339
|
|
186
340
|
## Helpers
|
187
|
-
* [Batches (Sidekiq Pro)](#batches)
|
341
|
+
* [Batches (Sidekiq Pro) _experimental_](#batches)
|
188
342
|
* [`within_sidekiq_retries_exhausted_block`](#within_sidekiq_retries_exhausted_block)
|
189
343
|
|
190
344
|
### Batches
|
191
|
-
|
345
|
+
|
346
|
+
If you are using Sidekiq Batches ([Sidekiq Pro feature][sidekiq_wiki_batches]),
|
347
|
+
You can *opt-in* with `stub_batches` to make `rspec-sidekiq` mock the
|
348
|
+
implementation (using a NullObject pattern). This enables testing without a
|
349
|
+
Redis instance. Mocha and RSpec stubbing is supported here.
|
350
|
+
|
351
|
+
:warning: **Caution**: Opting-in to this feature, while allowing you to test without
|
352
|
+
having Redis, _does not_ provide the exact API that `Sidekiq::Batch` does. As
|
353
|
+
such it can cause surprises.
|
354
|
+
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
RSpec.describe "Using mocked batches", stub_batches: true do
|
358
|
+
it "uses mocked batches" do
|
359
|
+
batch = Sidekiq::Batch.new
|
360
|
+
batch.jobs do
|
361
|
+
SomeJob.perform_async 123
|
362
|
+
end
|
363
|
+
|
364
|
+
expect(SomeJob).to have_enqueued_sidekiq_job
|
365
|
+
|
366
|
+
# Caution, the NullObject pattern means that the mocked Batch implementation
|
367
|
+
# responds to anything... even if it's not on the true `Sidekiq::Batch` API
|
368
|
+
# For example, the following fails
|
369
|
+
expect { batch.foobar! }.to raise_error(NoMethodError)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
```
|
192
373
|
|
193
374
|
### within_sidekiq_retries_exhausted_block
|
194
375
|
```ruby
|
@@ -202,10 +383,15 @@ FooClass.within_sidekiq_retries_exhausted_block {
|
|
202
383
|
```
|
203
384
|
|
204
385
|
## Testing
|
205
|
-
```
|
386
|
+
```
|
387
|
+
bundle exec rspec spec
|
388
|
+
```
|
206
389
|
|
207
390
|
## Maintainers
|
208
|
-
* @
|
391
|
+
* @wspurgin
|
392
|
+
|
393
|
+
### Alumni
|
394
|
+
|
209
395
|
* @packrat386
|
210
396
|
* @philostler
|
211
397
|
|
@@ -214,20 +400,10 @@ Please do! If there's a feature missing that you'd love to see then get in on th
|
|
214
400
|
|
215
401
|
Issues/Pull Requests/Comments all welcome...
|
216
402
|
|
217
|
-
[
|
218
|
-
[
|
219
|
-
[
|
220
|
-
|
221
|
-
[
|
222
|
-
[
|
223
|
-
[
|
224
|
-
[github]: http://github.com/philostler/rspec-sidekiq
|
225
|
-
[ruby_doc]: http://rubydoc.info/gems/rspec-sidekiq/frames
|
226
|
-
[ruby_gems]: http://rubygems.org/gems/rspec-sidekiq
|
227
|
-
[ruby_toolbox]: http://www.ruby-toolbox.com/projects/rspec-sidekiq
|
228
|
-
[travis_ci]: http://travis-ci.org/philostler/rspec-sidekiq
|
229
|
-
[travis_ci_badge]: https://travis-ci.org/philostler/rspec-sidekiq.svg?branch=develop
|
230
|
-
|
231
|
-
[rspec_sidekiq_wiki_faq_&_troubleshooting]: https://github.com/philostler/rspec-sidekiq/wiki/FAQ-&-Troubleshooting
|
232
|
-
[sidekiq_wiki_batches]: https://github.com/mperham/sidekiq/wiki/Batches
|
233
|
-
[sidekiq_wiki_delayed_extensions]: https://github.com/mperham/sidekiq/wiki/Delayed-Extensions
|
403
|
+
[github]: http://github.com/wspurgin/rspec-sidekiq
|
404
|
+
[github_actions]: https://github.com/wspurgin/rspec-sidekiq/actions
|
405
|
+
[github_actions_badge]: https://github.com/wspurgin/rspec-sidekiq/actions/workflows/main.yml/badge.svg
|
406
|
+
|
407
|
+
[rspec_sidekiq_wiki_faq_&_troubleshooting]: https://github.com/wspurgin/rspec-sidekiq/wiki/FAQ-&-Troubleshooting
|
408
|
+
[sidekiq_wiki_batches]: https://github.com/sidekiq/sidekiq/wiki/Batches
|
409
|
+
[sidekiq_wiki_delayed_extensions]: https://github.com/sidekiq/sidekiq/wiki/Delayed-Extensions
|
data/lib/rspec/sidekiq/batch.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/core"
|
4
|
+
require "rspec/support/fuzzy_matcher"
|
2
5
|
|
3
6
|
if defined? Sidekiq::Batch
|
4
7
|
module RSpec
|
@@ -9,7 +12,26 @@ if defined? Sidekiq::Batch
|
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
15
|
+
##
|
16
|
+
# Sidekiq::Batch is a Sidekiq::Pro feature. However the general consensus is
|
17
|
+
# that, by defeault, you can't test without redis. RSpec::Sidekiq includes
|
18
|
+
# a "null object" pattern implementation to mock Batches. This will mock
|
19
|
+
# Sidekiq::Batch and prevent it from using Redis.
|
20
|
+
#
|
21
|
+
# This is _opt-in_ only feature.
|
22
|
+
#
|
23
|
+
# RSpec.describe "Using mocked batches", stub_batches: true do
|
24
|
+
# it "uses mocked batches" do
|
25
|
+
# batch = Sidekiq::Batch.new
|
26
|
+
# batch.jobs do
|
27
|
+
# SomeJob.perform_async 123
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# expect(SomeJob).to have_enqueued_sidekiq_job
|
31
|
+
# end
|
32
|
+
# end
|
12
33
|
class NullBatch < NullObject
|
34
|
+
attr_accessor :description
|
13
35
|
attr_reader :bid
|
14
36
|
|
15
37
|
def initialize(bid = nil)
|
@@ -45,9 +67,17 @@ if defined? Sidekiq::Batch
|
|
45
67
|
def join
|
46
68
|
::Sidekiq::Worker.drain_all
|
47
69
|
|
48
|
-
@callbacks.each do |event,
|
70
|
+
@callbacks.each do |event, callback, options|
|
49
71
|
if event != :success || failures == 0
|
50
|
-
|
72
|
+
case callback
|
73
|
+
when Class
|
74
|
+
callback.new.send("on_#{event}", self, options)
|
75
|
+
when String
|
76
|
+
klass, meth = callback.split('#')
|
77
|
+
klass.constantize.new.send(meth, self, options)
|
78
|
+
else
|
79
|
+
raise ArgumentError, 'Unsupported callback notation'
|
80
|
+
end
|
51
81
|
end
|
52
82
|
end
|
53
83
|
end
|
@@ -62,7 +92,7 @@ if defined? Sidekiq::Batch
|
|
62
92
|
# :nocov:
|
63
93
|
RSpec.configure do |config|
|
64
94
|
config.before(:each) do |example|
|
65
|
-
next
|
95
|
+
next unless example.metadata[:stub_batches] == true
|
66
96
|
|
67
97
|
if mocked_with_mocha?
|
68
98
|
Sidekiq::Batch.stubs(:new) { RSpec::Sidekiq::NullBatch.new }
|
@@ -1,12 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "set"
|
5
|
+
|
1
6
|
module RSpec
|
2
7
|
module Sidekiq
|
3
8
|
class Configuration
|
4
|
-
attr_accessor :clear_all_enqueued_jobs,
|
9
|
+
attr_accessor :clear_all_enqueued_jobs,
|
10
|
+
:enable_terminal_colours,
|
11
|
+
:warn_when_jobs_not_processed_by_sidekiq
|
5
12
|
|
6
13
|
def initialize
|
7
|
-
|
14
|
+
# Display settings defaults
|
8
15
|
@enable_terminal_colours = true
|
16
|
+
|
17
|
+
# Functional settings defaults
|
18
|
+
@clear_all_enqueued_jobs = true
|
9
19
|
@warn_when_jobs_not_processed_by_sidekiq = true
|
20
|
+
@silence_warnings = Set.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def sidekiq_gte_7?
|
24
|
+
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
|
25
|
+
end
|
26
|
+
|
27
|
+
def sidekiq_gte_8?
|
28
|
+
Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("8.0.0")
|
29
|
+
end
|
30
|
+
|
31
|
+
def silence_warning(symbol)
|
32
|
+
@silence_warnings << symbol
|
33
|
+
end
|
34
|
+
|
35
|
+
def warn_for?(symbol)
|
36
|
+
!@silence_warnings.include?(symbol)
|
10
37
|
end
|
11
38
|
end
|
12
39
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sidekiq
|
2
4
|
module Worker
|
3
5
|
module ClassMethods
|
@@ -8,15 +10,15 @@ module Sidekiq
|
|
8
10
|
|
9
11
|
def default_retries_exhausted_message
|
10
12
|
{
|
11
|
-
'queue' => get_sidekiq_options[
|
13
|
+
'queue' => get_sidekiq_options['queue'],
|
12
14
|
'class' => name,
|
13
15
|
'args' => [],
|
14
|
-
'error_message' => 'An error
|
16
|
+
'error_message' => 'An error occurred'
|
15
17
|
}
|
16
18
|
end
|
17
19
|
|
18
20
|
def default_retries_exhausted_exception
|
19
|
-
StandardError.new('An error
|
21
|
+
StandardError.new('An error occurred')
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|