ruby-on-railsrspecrspec-railssidekiqrspec-sidekiq

Sidekiq::Testing.fake! not faking Sidekiq::Queue


I have a simple worker that is accessing the size of its own queue:

require 'sidekiq/api'

class TestWorker
  include Sidekiq::Worker

  def perform(*args)
    Sidekiq::Queue.new('test').size
  end
end

I am then testing this worker:

require 'rails_helper'

RSpec.describe TestWorker, type: :worker do
  describe '#perform' do
    it 'executes the job without connecting to Redis in the testing environment' do
      require 'sidekiq/testing'
      Sidekiq::Testing.fake! do
        TestWorker.perform_async
        TestWorker.drain
      end
    end
  end
end

This test is failing because it tries to access redis:

1) TestWorker#perform executes the job without connecting to Redis in the testing environment
     Failure/Error: Sidekiq::Queue.new('test').size

     Redis::CannotConnectError:
       Error connecting to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED)
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:344:in `rescue in establish_connection'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:328:in `establish_connection'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:99:in `block in connect'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:291:in `with_reconnect'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:98:in `connect'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:363:in `ensure_connected'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:219:in `block in process'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:304:in `logging'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:218:in `process'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/client.rb:118:in `call'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis.rb:1062:in `block in llen'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis.rb:45:in `block in synchronize'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis.rb:45:in `synchronize'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis.rb:1061:in `llen'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/api.rb:217:in `block in size'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq.rb:95:in `block in redis'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/connection_pool-2.2.2/lib/connection_pool.rb:65:in `block (2 levels) in with'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/connection_pool-2.2.2/lib/connection_pool.rb:64:in `handle_interrupt'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/connection_pool-2.2.2/lib/connection_pool.rb:64:in `block in with'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/connection_pool-2.2.2/lib/connection_pool.rb:61:in `handle_interrupt'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/connection_pool-2.2.2/lib/connection_pool.rb:61:in `with'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq.rb:92:in `redis'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/api.rb:217:in `size'
     # ./app/workers/test_worker.rb:7:in `perform'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:301:in `execute_job'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:296:in `block in process_job'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:128:in `block in invoke'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/middleware/chain.rb:133:in `invoke'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:295:in `process_job'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:279:in `drain'
     # ./spec/workers/test_worker_spec.rb:8:in `block (4 levels) in <top (required)>'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:16:in `__set_test_mode'
     # /home/matthieu/.rvm/gems/ruby-2.4.3/gems/sidekiq-5.1.3/lib/sidekiq/testing.rb:30:in `fake!'
     # ./spec/workers/test_worker_spec.rb:6:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # IO::EINPROGRESSWaitWritable:
     #   Operation now in progress - connect(2) would block
     #   /home/matthieu/.rvm/gems/ruby-2.4.3/gems/redis-4.0.1/lib/redis/connection/ruby.rb:180:in `connect_addrinfo'

According to Sidekiq documentation related to Sidekiq::Testing.fake! "instead of pushing jobs to Redis, Sidekiq pushes them into a jobs array which you can access"

Why is Sidekiq::Queue.new('test').size trying to connect to Redis instead of checking the size of the job array in the test environment?

Is there a way to make Sidekiq::Queue work with Sidekiq::Testing.fake! or should I mock it?


Solution

  • Sidekiq's API does not have a testing mode, [it] will always hit Redis.

    https://github.com/mperham/sidekiq/wiki/testing#api