Sidekiq Github wiki 中文文档
测试
commit信息:More details about using server middleware in tests | 提交者:ajw725 | 提交时间:2019-10-19 | 版本:dab35d7
Sidekiq给测试workers提供了一些选项。
设定
Sidekiq提供了以下三种测试模式:
- 测试仿冒者(fake),把所有的作业都推送到一个
jobs
数组 - inline模式,可以立即运行一个作业而不是给它排队
- 测试约束措施可以被关闭。 作业被推送到redis。
Sidekiq允许你使用下面方法动态配置测试工具:
require 'sidekiq/testing'
Sidekiq::Testing.fake! # fake is the default mode
Sidekiq::Testing.inline!
Sidekiq::Testing.disable!
警告: 请求
sidekiq/testing
会自动调用Sidekiq::Testing.fake!
,
因此你的作业将不会到达Redis。不要在任何生产代码中请求sidekiq/testing
。
以上的每个方法都可以接收一个block。
一个例子:
require 'sidekiq/testing'
Sidekiq::Testing.fake!
# Some tests
Sidekiq::Testing.inline! do
# Some other tests
end
# Here we're back to fake testing again.
要查询当前状态,请使用以下方法:
Sidekiq::Testing.enabled?
Sidekiq::Testing.disabled?
Sidekiq::Testing.fake?
Sidekiq::Testing.inline?
Testing Worker Queueing (Fake)
跟 ActionMailer
测试API相似,代替把作业推送给Redis,sidekiq把它们推送给你可获取的jobs
组数。在你的{test,spec}_helper.rb
文件中请求sidekiq/testing
文件,然后设置该模式:
require 'sidekiq/testing'
Sidekiq::Testing.fake!
然后断言这些作业会被推送到该队列:
expect {
HardWorker.perform_async(1, 2)
}.to change(HardWorker.jobs, :size).by(1)
assert_equal 0, HardWorker.jobs.size
HardWorker.perform_async(1, 2)
assert_equal 1, HardWorker.jobs.size
你可以通过清空该队列来执行所有排队的作业:
HardWorker.perform_async(1, 2)
HardWorker.perform_async(2, 3)
assert_equal 2, HardWorker.jobs.size
HardWorker.drain
assert_equal 0, HardWorker.jobs.size
用来执行所有workers排队的作业:
Sidekiq::Worker.drain_all
如果你不想在移除一些作业前实际执行它们:
HardWorker.perform_async(1, 2)
HardWorker.clear
assert_equal 0, HardWorker.jobs.size
清除所有workers的作业:
Sidekiq::Worker.clear_all
下面代码用来确保作业不会在测试之间徘徊:
RSpec.configure do |config|
config.before(:each) do
Sidekiq::Worker.clear_all
end
end
module SidekiqMinitestSupport
def after_teardown
Sidekiq::Worker.clear_all
super
end
end
class MiniTest::Spec
include SidekiqMinitestSupport
end
class MiniTest::Unit::TestCase
include SidekiqMinitestSupport
end
队列API(4.0+)
在4.0+版本上有一个有效的队列测试API。当被测试的应用程序中不存在Worker类时,这将很有帮助。一个使用Sidekiq::Client
来入队的作业:
Sidekiq::Client.push(
'class' => 'NonExistentWorker',
'queue' => 'other',
'args' => [1]
)
由于应用中没有NonExistentWorker
,我们可以确定是作业给队列制造的该问题:
assert_equal 0, Sidekiq::Queues["other"].size
Sidekiq::Client.push(
'class' => 'NonExistentWorker',
'queue' => 'other',
'args' => [1]
)
assert_equal 1, Sidekiq::Queues["other"].size
assert_equal "NonExistentWorker", Sidekiq::Queues["other"].first["class"]
# Clear an individual queue
Sidekiq::Queues["other"].clear
# Clear all queues (equivalent to Sidekiq::Worker.clear_all)
Sidekiq::Queues.clear_all
直接测试Workers
直接测试你的worker,就像对待ruby对象一样对待它。这很简单!
work = HardWorker.new
work.perform(1, 2)
内联测试Workers
通过在你的{test,spec}_helper.rb
文件中请求sidekiq/testing
文件,并且设置inline模式,可以在你的测试中内联运行Sidekiq workers。
require 'sidekiq/testing'
Sidekiq::Testing.inline!
# 或者使用块模式,这样能阻止泄露设置信息到其它的测试
Sidekiq::Testing.inline! do
HardWorker.perform_async
assert_worked_hard
end
当作业被放入该队列后,它们会被立即执行。
测试delay和delay_for方法
你可以从Sidekiq::Extensions::DelayedMailer
(ActionMailer), Sidekiq::Extensions::DelayedModel
(ActiveRecord), 或者 Sidekiq::Extensions::DelayedClass
(其它的)轻松地获取到作业的队列。
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
MyMailer.delay.send_welcome_email('foo@example.com')
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
测试Server中间件
默认,测试工具(每个模式中)不会运行任何的server端中间件。使用下面代码,你可以把中间件添加到其中:
Sidekiq::Testing.server_middleware do |chain|
chain.add AwesomeMiddleware
end
Sidekiq::Testing.server_middleware
栈中的中间件在inline
模式里每当作业被运行它就会被运行,在fake
模式中,每当.drain
或者 .perform_one
被调用时会被运行。
注意,如果你的中间件位于lib/sidekiq/middleware/server/awesome_middleware.rb
文件中,根据这里的描述,你将需要请求chain.add Sidekiq::Middleware::Server::AwesomeMiddleware
类,并且像下面这样定义它以便它能正确地加载到测试链中:
module Sidekiq::Middleware::Server
class AwesomeMiddleware
# do stuff
end
end
像class Sidekiq::Middleware::Server::AwesomeMiddleware
这样定义一个类在测试环境中将不能正确起作用,因为Sidekiq::Middleware::Server
不会被自动加载。你必须明确地请求中间件文件。
API
Sidekiq的API没有测试模式,也就是说,就像Sidekiq::ScheduledSet.new.each(...)
将总是命中Redis。你可以使用Sidekiq::Testing.disable!
来设置作业,以便在你的测试中对着一个真实地Redis实例使用该API。
测试Batches
Batches在许多作业之间高度地集成。在测试时,最终运行整个batch实现很困难:我建议手动触发回调而不是试着设置batch中间件。
Sidekiq::Testing.inline! do
b = Sidekiq::Batch.new
b.on(:success, SomeCallback)
b.jobs do
# inline will perform jobs immediately
5.times { HardWorker.perform_async }
end
# fire callback manually
SomeCallback.new.on_success(nil, nil)
end
RSpec
请查看rspec-sidekiq gem.
后台并发运行Capybara 功能测试
出自 https://makandracards.com/makandra/28125-perform-sidekiq-jobs-immediately-in-development
# config/environment/test.rb
# perform jobs immediately
config.active_job.queue_adapter = :sidekiq
require 'sidekiq/testing'
Sidekiq::Testing.inline!
...