Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #193 from rspec/hash_match_array_failure

Provide a clear failure message when using `{}.should =~ {}`.
  • Loading branch information...
commit cf52fe66fb76b6cdd529065a211a6a37aa738b51 2 parents abefb76 + c7a91af
@myronmarston myronmarston authored
View
2  lib/rspec/matchers.rb
@@ -684,6 +684,6 @@ def match_array(array)
BuiltIn::MatchArray.new(array)
end
- OperatorMatcher.register(Array, '=~', BuiltIn::MatchArray)
+ OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
end
end
View
18 lib/rspec/matchers/operator_matcher.rb
@@ -31,7 +31,7 @@ def initialize(actual)
def self.use_custom_matcher_or_delegate(operator)
define_method(operator) do |expected|
- if matcher = OperatorMatcher.get(@actual.class, operator)
+ if uses_generic_implementation_of?(operator) && matcher = OperatorMatcher.get(@actual.class, operator)
@actual.send(::RSpec::Matchers.last_should, matcher.new(expected))
else
eval_match(@actual, operator, expected)
@@ -62,6 +62,22 @@ def description
private
+ if Method.method_defined?(:owner) # 1.8.6 lacks Method#owner :-(
+ def uses_generic_implementation_of?(op)
+ @actual.method(op).owner == ::Kernel
+ end
+ else
+ def uses_generic_implementation_of?(op)
+ # This is a bit of a hack, but:
+ #
+ # {}.method(:=~).to_s # => "#<Method: Hash(Kernel)#=~>"
+ #
+ # In the absence of Method#owner, this is the best we
+ # can do to see if the method comes from Kernel.
+ @actual.method(op).to_s.include?('(Kernel)')
+ end
+ end
+
def eval_match(actual, operator, expected)
::RSpec::Matchers.last_matcher = self
@operator, @expected = operator, expected
View
15 spec/rspec/matchers/match_array_spec.rb
@@ -113,6 +113,17 @@ def ==(other)
MESSAGE
end
+ context "when the array defines a `=~` method" do
+ it 'delegates to that method rather than using the match_array matcher' do
+ array = []
+ def array.=~(other)
+ other == :foo
+ end
+
+ array.should =~ :foo
+ expect { array.should =~ :bar }.to fail_with(/expected: :bar/)
+ end
+ end
end
describe "should_not =~ [:with, :multiple, :args]" do
@@ -135,4 +146,8 @@ def ==(other)
it "fails with a string and the expected error message is given" do
expect { "I like turtles".should match_array([1,2,3]) }.to fail_with(/expected an array/)
end
+
+ it 'fails with a clear message when given a hash using the `should =~` syntax' do
+ expect { {}.should =~ {} }.to fail_with(/expected an array/)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.