Unexpected behavior with Matchers::Change and empty collections

The behavior of Spec::Matchers::Change in rspec 1.3.0 appears to
overlook a small corner case. When the initial value is {} or []
but the from clause is nil, rspec will report that the initial
value is correct. Of course, nil is not equal to either {} or
[]. Here’s a simple test case:

describe "Simple hash" do
  before :each do
    @c = Class.new do
      attr_accessor :apple
    end.new

    @c.apple = {} # or []
  end

  it "should change values with []= calls" do
    # False positive! The initial value is {} (or []), not nil.
    ->{ @c.apple = 100 }.should change(@c, :apple).from(nil).to(100)
  end
end

Running this produces no errors. However, if you switch things so that
the initial value of @c.apple is nil and the from clause is []
or {}, rspec’s behavior is now what you’d expect to see:

====
‘Simple hash should change values with []= calls’ FAILED
apple should have initially been {}, but was nil
/home/johnf/.rvm/gems/ruby-1.9.1-p378@standard/gems/rspec-1.3.0/lib/spec/expectations/fail_with.rb:41:in
fail_with' /home/johnf/.rvm/gems/ruby-1.9.1-p378@standard/gems/rspec-1.3.0/lib/spec/expectations/handler.rb:21:inhandle_matcher’
/home/johnf/.rvm/gems/ruby-1.9.1-p378@standard/gems/rspec-1.3.0/lib/spec/expectations/extensions/kernel.rb:27:in
`should’

Is this behavior by design?

John F.
Principal Consultant, Distilled Brilliance

On Jun 18, 2010, at 2:29 PM, John F. wrote:

   end.new

Running this produces no errors. However, if you switch things so that
/home/johnf/.rvm/gems/ruby-1.9.1-p378@standard/gems/rspec-1.3.0/lib/spec/expectations/extensions/kernel.rb:27:in
`should’

Is this behavior by design?

Yes. We deliberately made it so it would work this way :slight_smile:

Or …

No, please file a bug.

http://rspec.lighthouseapp.com for rspec-1
Issues · rspec/rspec-expectations · GitHub for rspec-2

Please include the same backtrace information. Thanks!

Cheers,
David