在测试Sidekiq/ActiveJob时,ActiveJob中有一个作业但是在Sidekiq中没有。

3

我对我的用户类(由Devise支持)进行了猴子补丁,以便像这样使用ActiveJob:

class User < ActiveRecord::Base
  # Omitted

  def send_devise_notification(notification, *args)
    devise_mailer.send(notification, self, *args).deliver_later
  end
end

我尝试使用以下测试来进行测试:

class UserTest < ActiveSupport::TestCase
  include ActiveJob::TestHelper

  def setup
    @user = User.new(email: 'example@gmail.com', password: 'password',
                     password_confirmation: 'password')
  end

  test 'send_devise_notification queues into activejob' do
    @user.save
    assert_equal enqueued_jobs.size, 1 # This test passes
    assert_equal Sidekiq::Extensions::DelayedMailer.jobs.size, 1 # This test fails
  end

log/test.log看起来像这样:

------------------------------------------------------------------
UserTest: test_0011_send_devise_notification queues into activejob
------------------------------------------------------------------
  [1m[35m (0.1ms)[0m  SAVEPOINT active_record_1
  [1m[36mUser Exists (0.4ms)[0m  [1mSELECT  1 AS one FROM "users" WHERE "users"."email" = 'example@gmail.com' LIMIT 1[0m
  [1m[35mUser Load (0.3ms)[0m  SELECT  "users".* FROM "users" WHERE "users"."confirmation_token" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["confirmation_token", "62d1fac8e1319c29bfbe630aece15975963994b09746edbad65772e4598aa4d2"]]
  [1m[36mSQL (0.4ms)[0m  [1mINSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at", "confirmation_token", "confirmation_sent_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"[0m  [["email", "example@gmail.com"], ["encrypted_password", "$2a$04$b6/WjVWCthq.bKG1KN8JPeb3w8jz8oVWTU53BpTn90wIlTQ5cC2KO"], ["created_at", "2015-01-30 06:19:03.531310"], ["updated_at", "2015-01-30 06:19:03.531310"], ["confirmation_token", "62d1fac8e1319c29bfbe630aece15975963994b09746edbad65772e4598aa4d2"], ["confirmation_sent_at", "2015-01-30 06:19:03.730092"]]
[ActiveJob] Enqueued ActionMailer::DeliveryJob (Job ID: 9730d5a8-5dd4-4334-8290-e4e8e554715e) to Test(mailers) with arguments: "Devise::Mailer", "confirmation_instructions", "deliver_now", gid://swyp/User/232633312, "s7QVW_T2Aw8-ik6o1g2f", {}
  [1m[35m (0.2ms)[0m  RELEASE SAVEPOINT active_record_1
  [1m[36m (0.2ms)[0m  [1mROLLBACK[0m
  [1m[35m (0.1ms)[0m  BEGIN

调试器中的enqueued_jobs如下:

[{:job=>ActionMailer::DeliveryJob,
:args=>["Devise::Mailer", "confirmation_instructions", "deliver_now", #<User id: 232633312, email: "example@gmail.com", encrypted_password: "$2a$04$E05.gR8oXSHQyk8hUOTBZ.PvswvHy2YYtTNXaha.wj2...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, confirmation_token: "cba7134de82b6fde115fd3ca8e40975befeac299a1e619cdcb...", confirmed_at: nil, confirmation_sent_at: "2015-01-30 17:08:51", unconfirmed_email: nil, created_at: "2015-01-30 17:08:51", updated_at: "2015-01-30 17:08:51", first_name: nil, last_name: nil>, "QBLzzPLKVLy3znSZESBc", {}], :queue=>"mailers"}]

bin/rails c --environment test

irb(main):004:0> Rails.application.config.active_job.queue_adapter
=> :sidekiq

我的 Procfile 如下所示:

web: bin/rails s
redis: redis-server
worker: bundle exec sidekiq -q default -q mailers

Anyone have any ideas?

2个回答

4

ActiveJob::TestHelper实际上并未将任务传递给适配器。如果您删除它,则会成为ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper的实例。


不幸的是,assert_equal ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper.jobs.size, 1 仍然失败。还有其他想法吗? - sunnyrjuneja
Mike说Sidekiq是ActiveJob的一个实例,这是正确的。然而,ActiveJob::TestHelper的一个细微之处是它实际上并没有直接添加任何内容到适配器的队列中。移除ActiveJob::TestHelper后,第二个测试通过了。我已经更新了他的答案以反映这一点。 - sunnyrjuneja
3
这是我最终所做的事情:https://medium.com/@chuckjhardy/testing-rails-activejob-with-rspec-5c3de1a64b66 - ChuckJHardy

1
在测试中,默认的适配器是TestAdapter(在日志中可以看到:[ActiveJob] Enqueued ActionMailer::DeliveryJob (Job ID: 9730d5a8-5dd4-4334-8290-e4e8e554715e) to Test(mailers) with arguments...)。 ActiveJob::TestHelper提供的enqueued_jobs和其他辅助工具正在查询TestAdapter,并且仅在测试中使用TestAdapter时才有效。
因此,您的第一个测试通过,因为作业由TestAdapter处理,但是您的第二个测试不会通过,因为来自TestAdapter的作业永远不会到达Sidekiq。

感谢您的澄清。我将Mike的答案标记为解决方案,因为使用他的答案,我能够首先调试问题。给你点赞,因为如果我先看到你的答案,它会为我解决问题。 - sunnyrjuneja

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接