LoginSignup
2
1

Rspecでモックを使用してテストを書いてみた

Last updated at Posted at 2024-02-29

mocksを使用した経緯

テストしたいクラスが、S3バケットへの署名付きURLの発行やCSVの生成などのために複数のクラスとの依存関係にあり、単独でテストをする必要があったため使用しました。

参考にした記事

mocksの基本について

ほぼほぼ上記の記事と同じ内容ではありますが、

hoge_spec.rb
let(:class_a) { instance_double(ClassA) }

これでClassAのテストダブル(影武者)のclass_aが作成できます。
しかし、このままではこのclass_aはメソッドなどは何も持っていないので情報を付与する必要があります。


hoge_spec.rb
allow(ClassA).to receive(:new).and_return(class_a)
allow(class_a).to receive(:upload)

これによって、まず
実際のコードでClassAをnewする際に、先ほど定義したテストダブルの方のclass_aが返されるようになります。
そしてテストダブルの方のclass_aにuploadメソッドを受け取れるように設定しています。(class_aがuploadメソッドを受け取ると何もしないようにモックしています)


またこのように書くことで何かしらの動作を持たせることもできました
hoge_spec.rb
allow(class_b).to receive(:call) do
# 何かしらclass_bに持たせたい処理をここに書ける
end

これによって、テスト内でも何かしらの処理を持たせることで、テストダブルに別のテストダブルを呼ばせるなどの動作も取れるようになります。今回はしていませんが。


これらの設定により、実際のコードで
「ClassAのインスタンスをnewしてuploadメソッドを行い処理を行う」
という実際の処理の工程を
「ClassAの実装の詳細を隔離したまま、class_aという代替品にuploadメソッドが届くかどうかの確認をする」
というやり方でテストを行えるようになります。

実際のテストの全体像

コードの全体像は以下のようになりました

hoge_spec.rb
require 'rails_helper'

RSpec.describe ClassHoge do
  describe '#call' do
    subject { 実際の処理.new.call(引数1, 引数2など) }
    
    let(:class_a) { instance_double(ClassA) }
    let(:class_b) { instance_double(ClassB) }

    before do
      allow(ClassA).to receive(:new).and_return(class_a)
      allow(class_a).to receive(:upload)
      allow(ClassB).to receive(:new).and_return(class_b)
      allow(class_b).to receive(:call) do
      # 何かしらclass_bに持たせたい処理をここに書ける
      end
    end

    it 'ClassAにhugaして、ほにゃららし、ClassBにhogeしてどうなる' do
      subject
      expect(class_b).to have_received(:call)
      expect(class_a).to have_received(:upload)
    end
  end
end
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1