【RSpec】モックを使ったテスト | Dev Driven 開発・デザインチーム 【RSpec】モックを使ったテスト | 働くひとと組織の健康を創る iCARE

BLOG

【RSpec】モックを使ったテスト

メグミ
2020/08/31

こんにちは!メグミです!

今回は モックを使ったテストの書き方について書きたいと思います!

はじめに

処理の中でジョブを呼んだりする場合があると思いますが、
実際のジョブのテストは別で作成しているので、ジョブが呼ばれたかのテストをしたい!
ということがありました。テストの書き方について理解が曖昧だったので調べてみました!

基本的な書き方

Articleモデルにtitleメソッドがある場合

allow(article).to receive(:title).and_return("タイトル")
allow(実装を置き換えたいオブジェクト).to receive(置き換えたいメソッド名).and_return(返却したい値やオブジェクト)

メソッドの引数が1つ以上ある場合

allow(article).to receive(:title).with(argument_1, argument_2).and_return("タイトル")

やりたいこと

ある処理の中でジョブが任意の引数を受け取って呼ばれているかテストしたい

以下のようなメール送信処理のジョブがあるとします。

class UserMailJob < ApplicationJob
  def perform(recipients, subject, body)
    # メール送信処理
  end
end

以下のクラスのsend_emailメソッドで宛先が入力されていればメール送信処理を非同期で実行します。
宛先が未入力であればジョブは呼ばれません。

class SomeClass
  def send_email(recipients, subject, body)
    if recipients.present?
      UserMailJob.perform_later(recipients, subject, body)
      { is_success: true, message: "送信処理を開始しました。") }
    else
      { is_success: false, message: "送信に失敗しました。") }
    end
  end
end

このような処理のテストを書く場合、
ジョブの処理についてのテストは別途書くべきなので、
このジョブが非同期で呼ばれているかのテストを書く必要があります。

let!(:recipients) { ["megumi@example.com", "helen@example.com"] }
let!(:subject) { "メールの件名です。" }
let!(:body) { "メールの本文です。" }
subject{ SomeClass.new.send_email(recipients, subject, body) }

before do
  # UserMailJob クラスの perform_later が任意の引数で呼ばれると true を返すようモック化
  allow(UserMailJob).to receive(:perform_later).with(recipients, subject, body).and_return(true)
end

context "宛先が入力されている場合" do
  it "メール送信処理が1回呼ばれること" do
    subject
    expect(UserMailJob).to have_received(:perform_later).with(recipients, title, body).once
  end
end

context "宛先が未入力の場合" do
  let!(:recipients) { nil }

  it "メール送信処理が呼ばれないこと" do
    subject
    expect(UserMailJob).not_to have_received(:perform_later).with(recipients, title, body)
  end
end

UserMailJobクラスをモック化し、
非同期であるperform_laterの処理が呼ばれることをテストできるようになりました!
また、withを使って引数を検証することで呼ばれないこともテストしています。

さいごに

他にもいろんなメソッドがあるので気になる方は調べてみてください!

以上、RSpecでのモックを使ったテストの書き方でした!

おわり