Ivor Horton
Ivor Horton

Reputation: 91

RSpec not_to does not show the correct result

Below is my code example.

MacBook-Pro:~ hehe$ irb
2.1.2 :001 > require 'rspec/expectations'
 => true 
2.1.2 :002 > include RSpec::Matchers
 => Object 
2.1.2 :003 > expect(4).to be_nil
RSpec::Expectations::ExpectationNotMetError: expected: nil
     got: 4
    from /Users/hehe/.rvm/gems/ruby-2.1.2/gems/rspec-expectations-3.0.3/lib/rspec/expectations/fail_with.rb:30:in `fail_with'
    from /Users/hehe/.rvm/gems/ruby-2.1.2/gems/rspec-expectations-3.0.3/lib/rspec/expectations/handler.rb:37:in `handle_failure'
    from /Users/hehe/.rvm/gems/ruby-2.1.2/gems/rspec-expectations-3.0.3/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
    from /Users/hehe/.rvm/gems/ruby-2.1.2/gems/rspec-expectations-3.0.3/lib/rspec/expectations/expectation_target.rb:54:in `to'
    from (irb):3
    from /Users/hehe/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :004 > expect(4).not_to be_nil
 => false

Since 4 is not nil and I expect expect(4).not_to be_nil to return true instead of false. Could anyone help to explain it?

Upvotes: 2

Views: 703

Answers (1)

Dylan Markow
Dylan Markow

Reputation: 124449

The return value of false doesn't mean it failed, it just means 4 isn't nil. If it failed, it would have raised an error.

RSpec uses a NegativeOperatorMatcher class to test not_to expectations (source code here):

class NegativeOperatorMatcher < OperatorMatcher
  def __delegate_operator(actual, operator, expected)
    return false unless actual.__send__(operator, expected)
    fail_with_message("expected not: #{operator} #{expected.inspect}\n         got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
  end
end

So basically, it returns false unless the actual value equals the expected value, in which case it continues on to fail the spec (i.e. there's no situation where a negative matcher like not_to will ever return true).

Upvotes: 2

Related Questions