Search code examples
rspecsidekiq

Rails / Rspec: How would I test #any? for Sidekiq?


I have a block:

def already_syncing?
  Sidekiq::Queue.new(queue_name).any? { |q| q.args[0] == car_id }
end

How would I test this? If I stub it out like this:

allow(Sidekiq::Queue).to receive_message_chain(:new, :any?) { true }

Then the condition in my actual block is not tested.


Solution

  • I think what you were looking for was and_yield:

    allow(Sidekiq::Queue).to receive_message_chain(:new, :any?).and_yield(<something>)

    Here's some sample code/specs for you (with values/method calls that I didn't know about stubbed out) that you can try yourself and change as you see fit:

    class SyncTest
      def already_syncing?
        Sidekiq::Queue.new(queue_name).any? { |q| q.args[0] == car_id }
      end
    
      private # values for these methods below arbitrarily defined
    
      def queue_name
        'test'
      end
    
      def car_id
        1
      end
    end
    
    RSpec.describe SyncTest do
      let(:sync_test) { described_class.new }
    
      describe '#already_syncing?' do
        let(:queue) { double('queue') }
        let(:already_syncing) { sync_test.already_syncing? }
    
        before do
          # I don't have Sidekiq available for testing, so just say
          # it's a generic class.
          stub_const('Sidekiq::Queue', Class.new)
          allow(Sidekiq::Queue).to \
            receive_message_chain(:new, :any?).and_yield(queue)
        end
    
        context "when queue's args[0] == car_id" do
          before do
            allow(queue).to receive(:args).and_return([1])
          end
    
          it 'returns true' do
            expect(already_syncing).to be true
          end
        end
    
        context "when queue's args[0] != car_id" do
          before do
            allow(queue).to receive(:args).and_return([0])
          end
    
          it 'returns false' do
            expect(already_syncing).to be false
          end
        end
      end
    end