下級エンジニアの綴

新しく発見したことを綴っていこうと思っています。夢はでっかく上級エンジニアになることです。

Rspecでインスタンスメソッドのテストに苦労したのでメモ

今回はRspecでメソッドのテストをしたかったのですが、メソッド内で定義しているメソッド先の処理のテストは記述したくなかったので、それを解決したメモになります。

rubyのコード

# 今回テストしたかったのはTest1のexecuteメソッドになります
Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつが一番の曲者でした
  end
end

Class Test2
  def self.execute(test_params)
    p test_params + 'test2'
  end
end

Class Test3
  def initialize(test_params)
    @test = test_params + 'test3'
  end

  def execute(test_params)
    p @test + test_params + 'test3'
  end
end

テストコード

require 'rails_helper'

RSpec.describe Test1 do
  describe 'テスト1'
    it 'interfaceのテスト'
      test = double('Test3:00000000')
      allow(Test2).to receive(:execute).and_return(true)
      allow(Test3).to receive(:new).and_return(test)
      allow(Test3.new("")).to receive(:execute).and_return(true)
      Test1.execute(anything)
    end
  end
end

Test3のテストコードですが、。最初は下記のように記述していました。

allow(Test3).to receive(:new)
allow(Test3.new("")).to receive(:execute)

↑だとexecuteを呼ぶ時にno method errorがでます。

Test3で定義しているexecuteはクラスメソッドではなくインスタンスメソッドなので、インスタンスにメソッドを定義しないとエラーが出てしましました。

なので、

test = double('Test3:00000000')

↑でインスタンスを定義して

allow(Test3).to receive(:new).and_return(test)

↑でnewした時の戻り値にインスタンスを返えすようにします。

allow(Test3.new("")).to receive(:execute)

↑でインスタンスにexecuteメソッドを定義することによって

Class Test1
  def self.execute(test_params)
    Test2.execute(test_params)
    Test3.new(test_params).execute(test_params) # ←こいつのテストが通るようになる
  end
end

Test3のテストが通るようになります。(解決するまでにめっちゃ時間がかかりました。

参考URL

qiita.com