Posted at

rspec-mocks の and_raise が ArgumentError になってしまう場合は例外クラスに引数を渡す

More than 1 year has passed since last update.

こういうテストがあるとする


spec/my_spec.rb

require 'spec_helper'

require 'rack-timeout'

class Klass
end

describe 'Rack::Timeout::RequestTimeoutException' do
it 'bad' do
expect(Klass).to receive(:new).and_raise(Rack::Timeout::RequestTimeoutException)
expect {
Klass.new
}.to raise_error(Rack::Timeout::RequestTimeoutException)
end

it 'good' do
expect(Klass).to receive(:new).and_raise(Rack::Timeout::RequestTimeoutException.new( {} ))
expect {
Klass.new
}.to raise_error(Rack::Timeout::RequestTimeoutException)
end
end


実行するとこうなる

$ rake

Rack::Timeout::RequestTimeoutException
bad (FAILED - 1)
good

Failures:

1) Rack::Timeout::RequestTimeoutException bad
Failure/Error:
expect {
Klass.new
}.to raise_error(Rack::Timeout::RequestTimeoutException)

expected Rack::Timeout::RequestTimeoutException, got #<ArgumentError: wrong number of arguments (given 0, expected 1)> with backtrace:
# ./spec/my_spec.rb:11:in `block (3 levels) in <top (required)>'
# ./spec/my_spec.rb:10:in `block (2 levels) in <top (required)>'
# ./spec/my_spec.rb:10:in `block (2 levels) in <top (required)>'

Finished in 0.0397 seconds (files took 0.28993 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/my_spec.rb:8 # Rack::Timeout::RequestTimeoutException bad

Rack::Timeout::RequestTimeoutException#initialize は引数を一つとるが and_raise に例外クラスそのものを渡すと new するとき引数を渡してくれないので ArgumentError がでてしまう。

https://github.com/heroku/rack-timeout/blob/bd7b37117867e224ed68c8cc9eed6256203ab169/lib/rack/timeout/core.rb#L12-L17

適当な引数を渡して作ったインスタンスを and_raise に渡せば、意図した通りに動く。


参考(っていうかこのブログ記事のほうがより詳しい)

https://tnakamura.hatenablog.com/entry/2015/02/02/rspec_mocks_and_raise