Job Spec

關於 Rails Active Job 請參考這篇文章 Active Job Basics

Rails 的 Active Job 是一層內建的抽象,抽象了背景任務的執行,測試也非常容易撰寫。

以下介紹 Job 常見的測試標的。

命名慣例

spec/jobs/[job_name]_spec.rb

譬如:

app/jobs/application_job.rb 對應的測試文件為 spec/jobs/application_job_spec.rb

app/jobs/build_job.rb 對應的測試文件為 spec/jobs/build_job_spec.rb

文件結構

# app/jobs/application_job.rb
class ApplicationJob < ActiveJob::Base
end


# app/jobs/user_contact_sync_job.rb
class UserContactSyncJob < ApplicationJob
  queue_as :low

  def perform(user)
    ...
  end
end

測試按 Job 內方法的撰寫順序來測:

# spec/jobs/user_contact_sync_job_spec.rb
require "rails_helper"

RSpec.describe UserContactSyncJob do
  it "queue as" do
    ...
  end

  describe "#perform" do
    ...
  end
end

require "rails_helper" 非常重要,這樣才會把 Rails 跟相關的設定(spec/rails_helper.rb)都載入進來。

T> 測試的順序建議跟 Job 方法的順序相同,這樣當測試文件行數變多的時候,才容易找到測試的位置,讀程序的人也比較好讀。重點是要保持一致性

要測什麼

個人建議將 Job 保持的越簡單越好,在 Job 只要檢查有正確傳遞消息,其餘的交給本來類別的單元測試。

  • queue 的名稱
  • 方法正確呼叫

以下是一個示例:

class UserContactSyncJob < ApplicationJob
  queue_as :high

  def perform(user)
    UserContactSync.new(user).start
    user.update(contact_refreshed: true)
  end
end

require "rails_helper"

RSpec.describe UserContactSyncJob do
  it "queue_as high" do
    expect(UserContactSyncJob.new.queue_name).to eq("high")
  end

  describe "perform" do
    it "syncs contacts and sets contact_refreshed to true" do
      user = create(:user, contact_refreshed: false)
      sync = double(:user_contact_sync, start: nil)
      allow(UserContactSync).to receive(:new).and_return(sync)

      UserContactSyncJob.perform_now(user)

      expect(UserContactSync).to have_received(:new).with(user)
      expect(sync).to have_received(:start)
      expect(user.reload).to be_contact_refreshed
    end
  end
end

延伸閱讀

Rails 官方關於測試 Active Job 的文章:Testing Jobs

results matching ""

    No results matching ""