LoginSignup
9
6

More than 5 years have passed since last update.

RSpec で Kernel.open をスタブする

Last updated at Posted at 2015-09-30

概要

app/controllers/hidamari_controller.rb
class HidamariController < ApplicationController
  # POST /hidamari/sketch
  def sketch
    ### 略 ###

    open('http://www.tbs.co.jp/anime/hidamari/')

    ### 略 ###
  end
end

上記のように open-uriKernel.open を使用しているコードがあります。
その単体テストで open が呼ばれることを確認したいです。

うーん、Kernel.open をスタブする方法がぱっと思い浮かばなかったので色々試してみました。

spec/controllers/hidamari_controller_spec.rb
# NG
expect(Kernel).to receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

# OK
expect_any_instance_of(Kernel).to \
  receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

# OK
expect_any_instance_of(Object).to \
  receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

# NG
expect_any_instance_of(BasicObject).to \
  receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

# OK (better)
#
# described_class == HidamariController #=> true
expect_any_instance_of(described_class).to \
  receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

# OK (best) ※ @jnchito さんにコメントで教えて頂きました。
# 
# controller は RSpec::Rails::ControllerExampleGroup に用意されている変数で、
# テスト対象のコントローラーのインスタンスが格納されています。
#
# controller.is_a?(HidamariController) #=> true
expect(controller).to \
  receive(:open).with('http://www.tbs.co.jp/anime/hidamari/')

post(:sketch)

controller をスタブする方法がもっともスマートだと思います。
expect_any_instance_of を使わずに expect で書ける (余計なスタブを行わずに済む) からです。

参考

9
6
3

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
9
6