RSpecメモ

前置き

忘れがちなRSpecのあれこれをメモします。随時更新です。

環境

本題

例外を期待する

class Sample
  def func
    raise StandardError.new
  end
end

describe Sample do
  describe "#func" do
    subject { described_class.new.func }

    it do
      expect { subject }.to raise_error(StandardError)
    end
  end
end

メソッドが呼ばれないことを期待する

subject { Foo.bar }

# barにてKernel.systemが呼ばれないことを期待する
it {
  expect(Kernel).not_to receive(:system)
}

事前条件などを共通化する

describe Sample do
  describe "#func" do
    shared_context "oな場合" do
      before {
        # 何か
      }
      let(:value) { 0 }
      after {
        # 何か
      }
    end

    context "xな場合" do
      include_context "oな場合"
    end

    context "yな場合" do
      include_context "oな場合"
    end
  end
end

メソッドチェーンをstubする

class FooService
  def call
    false
  end
end

describe do
  before do
    allow(FooService).to receive_message_chain("new.call").and_return(true)
  end

  it do
    expect(FooService.new.call).to be true
  end
end

時間を制御する

qiita.com

ブロック引数をstubする

describe do
    before do
      allow(array).to receive(:each).and_yield(0).and_yield(0).and_yield(0)
    end
    let(:array) { [1, 2, 3] }

    it {
      actual = []
      array.each {|num| actual << num }
      expect(actual).to eq [0, 0, 0]
    }
  end

定数をstubする

class Sample
  CONSTANT = "定数"
end

describe Sample do
  before do
    stub_const("Sample::CONSTANT", "スタブ化")
  end

  it do
    expect(Sample::CONSTANT).to eq "スタブ化"
  end
end

Mockとかに差し替えるすきもないから、対象クラスのインスタンスをとにかく差し替える

before {
  allow_any_instance_of(Integer).to receive(:to_s).and_return("0")
}

Rails.env.production?をstubする

before {
  allow(Rails.env).to receive(:production?).and_return(true)
}

HTTPをstubする

require 'webmock/rspec'
include WebMock::API

describe Client do
  describe "#request" do
    before {
      stub_request(:any, %r{#{maps.googleapis.com}})
        .to_return(
          status: 200,
          headers: {
            "Content-Type" => "application/json",
            "Content-Length" => body.size,
          },
          body: {
            status: "OK",
          }.to_json,
        )
    }
  end
end