开发者

RSpec's failing because it thinks ActiveRecord objects aren't equal

Very simple spec...

@post.user.should == @user

Spec fails even though both objects are identical in every way except their object_id. ActiveRecord objects should equal (==) if their id's are the same. The objects are being created using factory_girl. I've confirmed that neither object is a ".new_record?". Comparing @post.user.id and @user.id works.

Whats more is the behavior is not consistent. These tests were working and now they fail despite no ch开发者_高级运维anges.

  • Rails 3.1
  • rspec-2.6
  • factory_girl-2.0.5
  • factory_girl_rails-1.1.0
  • jruby 1.6.4 (ruby-1.9.2-p136)
  • windows7

I typically use spork but this happens without spork also.

Some more details:

The offending line of code appears to be the following in ActiveRecord::Base

def ==(comparison_object)
  super ||
    comparison_object.instance_of?(self.class) &&
    id.present? &&
    comparison_object.id == id
end

Specifically, the "instance_of?" check is failing when it shouldn't be. I checked the class hierarchy of both objects. However, when I check the class.id of each object, they are not equal.

Furthermore, the behavior is dependant on which command I run...

jruby -S bundle exec rspec spec (FAILS)
jruby -S bundle exec rspec spec\models (PASSES)
jruby -S bundle exec rspec spec\models\post_spec.rb (PASSES)

Setting cache_classes=true in my environments/test.rb file seems to fix this, but I don't think this should be necessary.


This ended up being really silly. The problem was I had my integration tests in /spec/integration instead of /spec/requests. Rspec/Rails was doing its loading magic in a specific set of directories only, but would run all tests from all directories (causing double loading).


These objects have different object_ids because of the way active record works. In the example you gave

@post.user.should == @user

@post.user and @user are completely separate objects in memory. Even if they are instances of the same class, and they have the same id field, they will never have the same object_id (apparently as long as cache_classes=false).

Other ORMs, such as data mapper, handle this with an identity map. In Rails 3.1 there is experimental identity map support in active record, but it is disabled by default.

See identity_map.rb for more info

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜