psyho / bogus

Fake library for Ruby
Other
359 stars 14 forks source link

ActiveRecord::AssociationTypeMismatch #32

Closed sporto closed 11 years ago

sporto commented 11 years ago

I have the following test:

describe Comment do
    fake(:user) { User }
    let(:comment) { Comment.new(user: user) }

    it "has a user" do
        expect(comment.user).to eq(user)
    end
end

As I am testing comment I don't want it to be a fake, but user I would like to be a fake.

Rspec fails with:

ActiveRecord::AssociationTypeMismatch:
   User(#70251274274320) expected, got User(#70251274343580)

Not sure if this should work or I should try to do things differently. Thanks.

psyho commented 11 years ago

It looks like we had a bug in "Fake#is_a?" which caused the association type mismatch.

However, even if it is possible to pass fakes to AR associations, I would advise against that, because it violates the "don't mock what you don't own" principle.

In order to pass a fake to an AR association, you have to know what AR does with it under the hood, which is (in pseudocode):

def user=(user)
  id_attr = user.primary_key
  id_value = user[id_attr]
  self.user_id = id_value
  @user = user
end

However, when you update your project to use a newer version of AR, this code might change, and all of your tests that depend on that behavior would break.

The way I deal with AR classes in my projects is that I treat them mostly as value types (rule of thumb: no conditionals in AR models). Since value types don't contain any logic, you are free to use them in your isolated tests. Destroy All Software has a lot more on this topic if you are interested.