😏
【Rspec】例外発生の後のインスタンスの状態を調べたい時の対処法
概要
あるサービスクラスで例外発生した際にサービスクラスの外で例外を拾うような実装だった場合に、
そのサービスクラス内のインスタンスの状態をどうやってテストすればいいかわからなかったので、調べてみた。
なにがしたいの?
例えば、仮に以下のようなサービスクラスがあったとする。(この実装が好ましいかどうかは今回は無視する)
sample.rb
class NameService
def initialize(user, company)
@user = user
@company = company
end
def execute
ActiveRecord::Base.transaction do
@user.update!(name: "テストユーザ")
@company.update!(name: "テスト会社")
end
end
end
company.update!
で例外を発生した場合に、ロールバックしたことを確かめるべく、@user
の状態をテストした場合どうしたらいいいのだろうか。
パッとおもついた感じにすると以下のような感じ?
sample_spec.rb
before do
allow_any_instance_of(Company).to \
receive(:update!).and_raise(StandardError)
NameService.new(user, company).execute
end
it '更新されていないこと' do
expect(user.reload.name).not_to eq "テストユーザ"
end
でもこれではうまくいかない。
なぜなら、そもそもこのサービスクラスで例外が発生しているので、単体テストにおいては正常に終了しない。
下記のようなエラーが出てくる。
ターミナル
Failure/Error: @company.update!(name: "テスト会社")
StandardError:
StandardError
どうしたらいい?
色々調べてみたが、下記のようにspecファイル内で例外を受け取るようにするのが手っ取り早い。
it '更新されていないこと' do
begin
NameService.new(user, company).execute
rescue
expect(user.reload.name).not_to eq "テストユーザ"
end
end
まとめ
今回は、ゴリ押しで例外発生後にどうやってRspecテストするかをまとめてみました。
本当は、こういうことせずに網羅的にテストできるように設計すること強く推奨します。
Discussion