Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 间谍是否是一个合适的方法来查看是否有人使用了Resque方法?_Ruby On Rails_Ruby_Rspec_Rake_Resque - Fatal编程技术网

Ruby on rails 间谍是否是一个合适的方法来查看是否有人使用了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

虽然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
  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
参数;因此,他们正在验证是否已使用这些显式参数在代理对象上调用了该方法。否则测试将失败,并说明从未调用过该方法或该方法未收到这些参数。