rspecでなんでも通すモックを定義してみた

rspecを初めて使ったので、モックを使うメモ
gemのmailを使ってGmailを送るメソッドがある。

require "mail"
# ...
      def send_alert_to_gmail(content)
        mail = Mail.new
        mail.from = CONFIG['email']
        mail.to = CONFIG['to']
        mail.charset = "UTF8"
        mail.body = content
        mail.delivery_method :smtp, {
          :address => 'smtp.gmail.com',
          :port => 587,
          :domain => 'smtp.gmail.com',
          :user_name => CONFIG['email'],
          :password => CONFIG['password'],
          :authentication => :plain,
          :enable_starttls_auto => true
        }
        mail.deliver # ここを発行したくない
      end

# ...

これのテストコード(一部)

# ...
describe '#send_to_gmail' do
  it 'can send' do
    mail = mock(:mail).as_null_object # とりあえずなんでも通しちゃうメソッドを定義
    mail.should_receive(:deliver).once # 一回だけ呼ばれるメソッド
    Mail.stub(:new) { mail }

    Logger.send_alert_to_gmail "yeah!" # mail.deliver を含むメソッド
  end
end

このように外部に作用する(mailを送る)アクションを外に逃すようなアクションを stub out という、らしい。

これはたぶん良い例とは言えない。本当はメールを送るまでのアクションもチェックしたかったのだが、null_objectを定義すると全部逃がしてしまう。関数内部でMailへのアクションがほとんどを占める関数なので、このテストには不適な気がする。

ちなみにmail自体がモックの仕組みを持っている(MailTester)のだが、壊れていた。Exampleのテストが失敗する。
今回は動くコードができたので多少は仕方ないとしても、Issueが100件以上無視されてるモジュールを使うのはやめようとおもった。

でもmailはRails内部でも使われてるらしい。怖い。