respond_to
マッチャー
respond_to
マッチャーを使用して、オブジェクトのインターフェースの詳細を指定します。基本的な形式は次のとおりです:
expect(obj).to respond_to(:foo) # obj.respond_to?(:foo) が true の場合にパスする
マッチャーに複数の引数を渡すことで、オブジェクトが複数のメッセージに応答することを指定することもできます:
expect(obj).to respond_to(:foo, :bar) # obj.respond_to?(:foo) && obj.respond_to?(:bar) が true の場合にパスする
メソッドが受け入れる引数の数が重要な場合は、それも指定することができます:
expect(obj).to respond_to(:foo).with(1).argument
expect(obj).to respond_to(:bar).with(2).arguments
expect(obj).to respond_to(:baz).with(1..2).arguments
expect(obj).to respond_to(:xyz).with_unlimited_arguments
Rubyのバージョンがキーワード引数をサポートしている場合、メソッドが受け入れるキーワードのリストを指定することができます。
expect(obj).to respond_to(:foo).with_keywords(:ichi, :ni)
expect(obj).to respond_to(:bar).with(2).arguments.and_keywords(:san, :yon)
expect(obj).to respond_to(:baz).with_arbitrary_keywords
このマッチャーは完全に #respond_to?
に依存していることに注意してください。オブジェクトが #method_missing
を介して動的にメッセージに応答するが、#respond_to?
を介してこれを示さない場合、このマッチャーは誤った結果を返します。
基本的な使用法
次の内容で "respond_to_matcher_spec.rb" という名前のファイルがあるとします:
RSpec.describe "a string" do
it { is_expected.to respond_to(:length) }
it { is_expected.to respond_to(:hash, :class, :to_s) }
it { is_expected.not_to respond_to(:to_model) }
it { is_expected.not_to respond_to(:compact, :flatten) }
# deliberate failures
it { is_expected.to respond_to(:to_model) }
it { is_expected.to respond_to(:compact, :flatten) }
it { is_expected.not_to respond_to(:length) }
it { is_expected.not_to respond_to(:hash, :class, :to_s) }
# mixed examples--String responds to :length but not :flatten
# both specs should fail
it { is_expected.to respond_to(:length, :flatten) }
it { is_expected.not_to respond_to(:length, :flatten) }
end
rspec respond_to_matcher_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 10 の例、6 の失敗 | | "a string" が :to_model に応答することを期待しました | | "a string" が :compact, :flatten に応答することを期待しました | | "a string" が :length に応答しないことを期待しました | | "a string" が :hash, :class, :to_s に応答しないことを期待しました | | "a string" が :flatten に応答することを期待しました | | "a string" が :length に応答しないことを期待しました |
引数の指定
次の内容で "respond_to_matcher_argument_checking_spec.rb" という名前のファイルがあるとします:
RSpec.describe 7 do
it { is_expected.to respond_to(:zero?).with(0).arguments }
it { is_expected.not_to respond_to(:zero?).with(1).argument }
it { is_expected.to respond_to(:between?).with(2).arguments }
it { is_expected.not_to respond_to(:between?).with(7).arguments }
# deliberate failures
it { is_expected.to respond_to(:zero?).with(1).argument }
it { is_expected.not_to respond_to(:zero?).with(0).arguments }
it { is_expected.to respond_to(:between?).with(7).arguments }
it { is_expected.not_to respond_to(:between?).with(2).arguments }
end
rspec respond_to_matcher_argument_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 8 例、4 失敗 | | 7 に対して :zero? メソッドが 1 つの引数で呼び出されることを期待しています | | 7 に対して :zero? メソッドが 0 個の引数で呼び出されないことを期待しています | | 7 に対して :between? メソッドが 7 個の引数で呼び出されることを期待しています | | 7 に対して :between? メソッドが 2 個の引数で呼び出されないことを期待しています |
引数の範囲を指定する
以下の内容で "respond_to_matcher_argument_range_checking_spec.rb" という名前のファイルを作成します:
class MyClass
def build(name, options = {})
end
def inspect
'my_object'
end
end
RSpec.describe MyClass do
it { is_expected.to respond_to(:build).with(1..2).arguments }
it { is_expected.not_to respond_to(:build).with(0..1).arguments }
it { is_expected.not_to respond_to(:build).with(2..3).arguments }
it { is_expected.not_to respond_to(:build).with(0..3).arguments }
# deliberate failures
it { is_expected.not_to respond_to(:build).with(1..2).arguments }
it { is_expected.to respond_to(:build).with(0..1).arguments }
it { is_expected.to respond_to(:build).with(2..3).arguments }
it { is_expected.to respond_to(:build).with(0..3).arguments }
end
rspec respond_to_matcher_argument_range_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 8 例、4 失敗 | | my_object に対して 1 〜 2 個の引数で :build メソッドが呼び出されな いことを期待しています | | my_object に対して 0 〜 1 個の引数で :build メソッドが呼び出されることを期待しています | | my_object に対して 2 〜 3 個の引数で :build メソッドが呼び出されることを期待しています | | my_object に対して 0 〜 3 個の引数で :build メソッドが呼び出されることを期待しています |
無制限の引数を指定する
以下の内容で "respond_to_matcher_unlimited_argument_checking_spec.rb" という名前のファイルを作成します:
class MyClass
def greet(message = 'Hello', *people)
end
def hail(person)
end
def inspect
'my_object'
end
end
RSpec.describe MyClass do
it { is_expected.to respond_to(:greet).with_unlimited_arguments }
it { is_expected.to respond_to(:greet).with(1).argument.and_unlimited_arguments }
it { is_expected.not_to respond_to(:hail).with_unlimited_arguments }
it { is_expected.not_to respond_to(:hail).with(1).argument.and_unlimited_arguments }
# deliberate failures
it { is_expected.not_to respond_to(:greet).with_unlimited_arguments }
it { is_expected.not_to respond_to(:greet).with(1).argument.and_unlimited_arguments }
it { is_expected.to respond_to(:hail).with_unlimited_arguments }
it { is_expected.to respond_to(:hail).with(1).argument.and_unlimited_arguments }
end
rspec respond_to_matcher_unlimited_argument_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 8 例、4 失敗 | | my_object に対して無制限の引数で :greet メソッドが呼び出されないことを期待しています | | my_object に対して 1 つの引数と無制限の引数で :greet メソッドが呼び出されないことを期待しています | | my_object に対して無制限の引数で :hail メソッドが呼び出されることを期待しています | | my_object に対して 1 つの引数と無制限の引数で :hail メソッドが呼び出されることを期待しています |
キーワードを指定する
以下の内容で "respond_to_matcher_keyword_checking_spec.rb" という名前のファイルを作成します:
class MyClass
def find(name = 'id', limit: 1_000, offset: 0)
[]
end
def inspect
'my_object'
end
end
RSpec.describe MyClass do
it { is_expected.to respond_to(:find).with_keywords(:limit, :offset) }
it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) }
it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset, :page) }
it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) }
# deliberate failures
it { is_expected.to respond_to(:find).with_keywords(:limit, :offset, :page) }
it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) }
it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset) }
it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) }
end
rspec respond_to_matcher_keyword_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 8 例、4 失敗 | | my_object に対して :limit、:offset、:page のキーワードを指定して :find メソッドが呼び出されることを期待しています | | my_object に対して 1 つの引数と :limit、:offset、:page のキーワードを指定して :find メソッドが呼び出されることを期待しています | | my_object に対して :limit、:offset のキーワードを指定して :find メソッドが呼び出されないことを期待しています | | my_object に対して 1 つの引数と :limit、:offset のキーワードを指定して :find メソッドが呼び出されないことを期待しています |
キーワードを指定する
ファイル名が "respond_to_matcher_any_keywords_checking_spec.rb" の場合、以下の内容を持つとします:
class MyClass
def build(name: 'object', **opts)
end
def create(name: 'object', type: String)
end
def inspect
'my_object'
end
end
RSpec.describe MyClass do
it { is_expected.to respond_to(:build).with_any_keywords }
it { is_expected.to respond_to(:build).with_keywords(:name).and_any_keywords }
it { is_expected.not_to respond_to(:create).with_any_keywords }
it { is_expected.not_to respond_to(:create).with_keywords(:name).and_any_keywords }
# deliberate failures
it { is_expected.not_to respond_to(:build).with_any_keywords }
it { is_expected.not_to respond_to(:build).with_keywords(:name).and_any_keywords }
it { is_expected.to respond_to(:create).with_any_keywords }
it { is_expected.to respond_to(:create).with_keywords(:name).and_any_keywords }
end
rspec respond_to_matcher_any_keywords_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 8 つの例、4 つの失敗 | | :build にキーワードを含まないように my_object が応答しないことが期待されます | | :name とキーワードを含むように :build に my_object が応答しないことが期待されます | | :create にキーワードを含むように my_object が応答することが期待されます | | :name とキーワードを含むように :create に my_object が応答することが期待されます |
必須キーワードを指定する
ファイル名が "respond_to_matcher_required_keyword_checking_spec.rb" の場合、以下の内容を持つとします:
class MyClass
def plant(seed:, fertilizer: nil, water: 'daily')
[]
end
def inspect
'my_object'
end
end
RSpec.describe MyClass do
it { is_expected.to respond_to(:plant).with_keywords(:seed) }
it { is_expected.to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) }
it { is_expected.not_to respond_to(:plant).with_keywords(:fertilizer, :water) }
# deliberate failures
it { is_expected.not_to respond_to(:plant).with_keywords(:seed) }
it { is_expected.not_to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) }
it { is_expected.to respond_to(:plant).with_keywords(:fertilizer, :water) }
end
rspec respond_to_matcher_required_keyword_checking_spec.rb
を実行すると、
以下のすべてが出力に含まれるはずです:
| 6 つの例、3 つの失敗 | | :seed をキーワードとして含むように my_object が応答しないことが期待されます | | :seed, :fertilizer, :water をキーワードとして含むように my_object が応答しないことが期待されます | | :fertilizer と :water をキーワードとして含むように my_object が応答することが期待されます |