LoginSignup
2
1

More than 1 year has passed since last update.

【RSpec】raise_error, changeマッチャーを繋げて使いたい

Last updated at Posted at 2022-02-19

例外を投げることを確認しつつ、値が変化することも確認したい

下記のようなクラスがあった時に、
StandardErrorを投げることと、@numの値が増えることを確認したい。

テスト対象のクラス
class TestTarget
  attr_reader :num

  def initialize
    @num = 0
  end

  def call!
    @num += 1
    raise StandardError
  end
end

マッチャーを繋げない書き方

raise_errorマッチャーで期待値を確認する前後の行で、値の変化を確認するとこうなる。

RSpec.describe 'TestTarget#call!' do
  it '例外を投げ、@numの値が増える' do
    t = TestTarget.new

    # expect { t.call! }.to change(t, :num).by(1) のように書きたいけど、
    # 例外が発生するから確認できない。
    expect(t.num).to eq 0
    expect { t.call! }.to raise_error(StandardError)
    expect(t.num).to eq 1
  end
end

マッチャーを繋げる書き方

マッチャーの戻り値に対してandorメソッドを繋げることで、
raise_errorマッチャーの後ろにchangeマッチャーを繋げて書ける。

参考: https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/compound-expectations

RSpec.describe 'TestTarget#call!' do
  it '例外を投げ、@numの値が増える' do
    t = TestTarget.new

    # 引数渡しも、ブロック渡しも書ける。
    expect { t.call! }.to raise_error(StandardError).and change(t, :num).by(1)
    # or
    expect { t.call! }.to raise_error(StandardError).and change { t.num }.by(1)
  end
end

changeマッチャーの否定系(not)も確認したい場合

既存マッチャーの否定系を簡単に定義する機能を使って書ける。

参考: https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/define-negated-matcher

RSpec.describe 'TestTarget#call!' do
  before do
    # changeマッチャーの否定系を定義
    RSpec::Matchers.define_negated_matcher :not_change, :change
  end

  it '例外を投げ、@numの値が変化しない' do
    t = TestTarget.new

    # 引数渡しも、ブロック渡しも書ける。
    expect { t.call! }.to raise_error(StandardError).and not_change(t, :num)
    # or
    expect { t.call! }.to raise_error(StandardError).and not_change { t.num }
  end
end

最後に

@harashoo さんの記事も参考にさせていただきました。ありがとうございます。
※ RSpecのバージョン3.10.0で動作確認を行っています。

2
1
0

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
2
1