Ruby on rails 间谍是否是一个合适的方法来查看是否有人使用了Resque方法?
虽然simple coverage将此报告为100%覆盖,但我并不满意。标记为focus的规范我想确认所有的Resque方法都被激发。间谍还是双重间谍才是正确的方法 规格Ruby on rails 间谍是否是一个合适的方法来查看是否有人使用了Resque方法?,ruby-on-rails,ruby,rspec,rake,resque,Ruby On Rails,Ruby,Rspec,Rake,Resque,虽然simple coverage将此报告为100%覆盖,但我并不满意。标记为focus的规范我想确认所有的Resque方法都被激发。间谍还是双重间谍才是正确的方法 规格 describe 'resque tasks' do include_context 'rake' let(:task_paths) { ['tasks/resque'] } before do invoke_task.reenable end # rubocop:disable all d
describe 'resque tasks' do
include_context 'rake'
let(:task_paths) { ['tasks/resque'] }
before do
invoke_task.reenable
end
# rubocop:disable all
describe 'resque' do
context ':setup' do
let(:task_name) { 'resque:setup' }
it 'works' do
invoke_task.invoke
expect(Resque.logger.level).to eq(1)
end
end
context ':scheduler_setup' do
let(:task_name) { 'resque:scheduler_setup' }
it 'works' do
expect(invoke_task.invoke).to be
end
end
context ':clear', focus: true do
let(:task_name) { 'resque:clear' }
it 'works' do
expect(Resque).to receive(:remove_queue).with('queue:default').and_return(true)
expect { invoke_task.invoke }.to output(
"Clearing default...\n"\
"Clearing delayed...\n"\
"Clearing stats...\n"\
"Clearing zombie workers...\n"\
"Clearing failed jobs...\n"\
"Clearing resque workers...\n"
).to_stdout
end
end
end
describe 'jobs:work' do
let(:task_name) { 'jobs:work' }
it 'works' do
expect_any_instance_of(Object).to receive(:system).with("bundle exec env rake resque:workers QUEUE='*' COUNT='#{ENV['WEB_WORKERS']}'").and_return(true)
expect(invoke_task.invoke).to be
end
end
# rubocop:enable all
end
重新设置Rake任务
require 'resque'
require 'resque/tasks'
require 'resque/scheduler/tasks'
# http://jademind.com/blog/posts/enable-immediate-log-messages-of-resque-workers/
namespace :resque do
desc 'Initialize Resque environment'
task setup: :environment do
ENV['QUEUE'] ||= '*'
Resque.logger.level = Logger::INFO
end
task scheduler_setup: :environment
# see http://stackoverflow.com/questions/5880962/how-to-destroy-jobs-enqueued-by-resque-workers - old version
# see https://github.com/defunkt/resque/issues/49
# see http://redis.io/commands - new commands
desc 'Clear pending tasks'
task clear: :environment do
queues = Resque.queues
queues.each do |queue_name|
puts "Clearing #{queue_name}..."
Resque.remove_queue("queue:#{queue_name}")
end
puts 'Clearing delayed...'
Resque.redis.keys('delayed:*').each do |key|
Resque.redis.del key.to_s
end
Resque.redis.del 'delayed_queue_schedule'
Resque.reset_delayed_queue
puts 'Clearing stats...'
Resque.redis.set 'stat:failed', 0
Resque.redis.set 'stat:processed', 0
puts 'Clearing zombie workers...'
Resque.workers.each(&:prune_dead_workers)
puts 'Clearing failed jobs...'
cleaner = Resque::Plugins::ResqueCleaner.new
cleaner.clear
puts 'Clearing resque workers...'
Resque.workers.each(&:unregister_worker)
end
end
desc 'Alias for resque:work'
# http://stackoverflow.com/questions/10424087/resque-multiple-workers-in-development-mode
task 'jobs:work' do
system("bundle exec env rake resque:workers QUEUE='*' COUNT='#{ENV['WEB_WORKERS']}'")
end
共享上下文
shared_context 'rake' do
let(:invoke_task) { Rake.application[task_name] }
let(:highline) { instance_double(HighLine) }
before do
task_paths.each do |task_path|
Rake.application.rake_require(task_path)
end
Rake::Task.define_task(:environment)
end
before do
allow(HighLine).to receive(:new).and_return(highline)
end
end
标记为focus的规范我想确认所有的Resque方法都被激发。间谍还是双重间谍才是正确的方法
对。此测试中的间谍只会测试它是否收到了这些方法调用,因为它充当了这些测试的替身;这意味着您在测试中没有测试任务的行为,而是测试任务是否有一个对象,如Resque
接收这些方法调用
间谍
在调用测试代码之前,将示例的期望值放在开始处。许多开发人员更喜欢使用act-arrange-assert(或当时给定的)模式来构造测试。Spies是另一种类型的双重测试,通过使用have\u received
,您可以期望在事件发生后收到消息,从而支持此模式
--
您的it“起作用”测试的示例
it 'works' do
expect(Resque).to receive(:remove_queue).with('queue:default').and_return(true)
expect { invoke_task.invoke }.to output(
"Clearing default...\n"\
"Clearing delayed...\n"\
"Clearing stats...\n"\
"Clearing zombie workers...\n"\
"Clearing failed jobs...\n"\
"Clearing resque workers...\n"
).to_stdout
end
详情如下:
RSpec.describe "have_received" do
it 'works' do
Rake::Task.define_task(:environment)
invoke_task = Rake.application['resque:clear']
redis_double = double("redis")
allow(redis_double).to receive(:keys).with('delayed:*').and_return([])
allow(redis_double).to receive(:del).with('delayed_queue_schedule').and_return(true)
allow(redis_double).to receive(:set).with('stat:failed', 0).and_return(true)
allow(redis_double).to receive(:set).with('stat:processed', 0).and_return(true)
allow(Resque).to receive(:queues).and_return([])
allow(Resque).to receive(:redis).and_return(redis_double)
# allow(Resque).to receive(:remove_queue).with('queue:default') #.and_return(true)
allow(Resque).to receive(:reset_delayed_queue) #.and_return(true)
allow(Resque).to receive(:workers).and_return([])
cleaner_double = double("cleaner")
allow(Resque::Plugins::ResqueCleaner).to receive(:new).and_return(cleaner_double)
allow(cleaner_double).to receive(:clear).and_return(true)
expect { invoke_task.invoke }.to output(
# "Clearing default...\n"\
"Clearing delayed...\n"\
"Clearing stats...\n"\
"Clearing zombie workers...\n"\
"Clearing failed jobs...\n"\
"Clearing resque workers...\n"
).to_stdout
expect(redis_double).to have_received(:keys)
expect(redis_double).to have_received(:del)
expect(redis_double).to have_received(:set).with('stat:failed', 0)
expect(redis_double).to have_received(:set).with('stat:processed', 0)
expect(Resque).to have_received(:queues)
expect(Resque).to have_received(:redis).at_least(4).times
# expect(Resque).to have_received(:remove_queue).with('queue:default')
expect(Resque).to have_received(:reset_delayed_queue)
expect(Resque).to have_received(:workers).twice
expect(Resque::Plugins::ResqueCleaner).to have_received(:new)
expect(cleaner_double).to have_received(:clear)
end
end
注意事项:
allow(Resque).to receive(:remove_queue).with('queue:default')
被注释掉,因为allow(redis_double).to receive(:keys).with('delayed:')。and_return([])
在我的示例代码中返回一个空数组,这意味着队列。每个从不迭代一次,因此Resque.remove_queue('queue:{queue{queue_name})从不调用
,并且不会为预期输出返回
“清除默认…\n”\
- 此外,在这一项任务中发生了很多事情,将其分解为更小的任务可能是值得的
这将有效地存根Resque
对象上的每个预期方法调用,然后在调用任务后访问double接收这些预期方法调用的情况。它不测试这些任务的结果,只测试方法调用的发生和确认
方法正在被激发
参考文献:
我做了一些调整,但这个答案很完美。非常感谢你。如果我可以问一个后续问题,有没有一种方法可以设置一个期望值,它使用和(this | | that)
来验证参数?我想说,验证参数是一种暗示,当像expect(redis_double.)这样的行时,接收(:set)。with('stat:failed',0)
,redis\u double
对象的方法set
希望接收的stat:failed
和0
参数;因此,他们正在验证是否已使用这些显式参数在代理对象上调用了该方法。否则测试将失败,并说明从未调用过该方法或该方法未收到这些参数。