Minitest で stub

最近, Minitest 楽しいマンになりつつありますが、 RSpec に慣れた体にはいろいろと書き方に困ることがあります。

mock, stub の使い方を毎回ググったりしてるのでメモ

## app/models/car.rb
class Car
  def drive
    update(status: 'driving')
    SlackNotifier.new.notify("Start to drive: id-#{id}")
  end
end


## spec/models/car_spec.rb
require 'minitest/mock'

describe Car do
  let(:car) { Car.new }

  describe '#drive' do
    specify do
      # How to write the test...??
    end
  end
end

基本的に依存のあるクラス等をよぶ場合は引数として渡されることを想定してたりするので、今回みたいなメソッドは今のままだとテストできません

なので以下のようにリファクタリングすればいけます

## app/models/car.rb
class Car
  def drive
    update(status: 'driving')
    notifier.notify("Start to drive: id-#{id}")
  end

  private

  def notifier
    @notifier ||= SlackNotifier.new
  end
end


## spec/models/car_spec.rb
require 'minitest/mock'

describe Car do
  let(:car) { Car.new }
  let(:notifier) { MiniTest::Mock.new }

  describe '#drive' do
    specify do
      notifier.expect :notify, true, ["Start to drive: id-#{car.id}"]
      car.stub :notifier, notifier do
        car.drive
        assert notifier.verify
      end
    end
  end
end

途中で呼ばれてるメソッドとかはなんとなく想像でお願いします。

参考

Contents