assaulter's diary

主にバイクについて

Rubyでインスタンスに対して固有のメソッドを定義する

テスト時に、特定のメソッドが実行されているかどうかを確認したい時に、こういう方法を使ったのでメモ。

要件

private な send_mail メソッドが、実行されていることをRSpecで確認したい。

ベースとなるクラス

class Some
  def execute
    # 状況に応じてsend_mailを実行したり、しなかったりする
  end
  
  private 
  
  def send_mail
    # メールが送信される的な
  end
end

RSpec内の記述

it 'send_mailメソッドが実行されること' do
  some = Some.new
  class << some
    # someの特異クラス内
    attr_accessor :is_executed
    def send_mail
      @is_executed = true
    end
  end

  some.execute
  expect(some.is_executed).to be_true
end

局所的にやるんだったら上記の記述でおkですが、複数同じことやるんだったらこんな感じにもできます。

module SendMailChecker
  attr_accessor :is_executed
    def send_mail
      @is_executed = true
    end
end

it 'send_mailが実行されること' do
  some = Some.new
  some.extend(SendMailChecker)
  
  some.execute
  expect(some.is_executed).to be_true
end

オブジェクト.extendしてあげると、オブジェクトの特異クラスにモジュールを取り込むことになるので、先ほどの書き方と一緒になるというわけです。

参考:Ruby7不思議 - 特異クラス・特異メソッド・クラスメソッド - basyura's blog