Wed, 12 Jul 06

Using in memory Active Record objects with associations for testing

Hitting the database in testing is bad.

Something that I’ve found relatively useful at work is to use real Active Record objects without any persistence (basically use AR#new and not AR#save[!] or AR#create[!]). When using standard techniques to create the association objects in memory you only get one side of the association at a time. Consider the following.

class Person < ActiveRecord::Base
  has_many :addresses
end
class Address < ActiveRecord::Base
  belongs_to :person
end

# One sided relationship with parent getting access to child
chris = Person.new
home = chris.addresses.build

chris.addresses.first
=> #<home>
home.person
=> nil

# One sided relationship with child getting access to parent
home = Address.new
chris = home.build_person

chris.addresses
=> []
home.person
=> #<chris>

# The example above that creates the address first could also have been written as.
# chris = Person.new
# home = Address.new(:person => chris)

You can see that in each case, only one side of the relationship has access to the other. If we were persisting the objects then the relationship would be two way via a database lookup. We can get a two way relationship in memory; although it has a certain duplication smell about it. Assuming the same models as above, we can amend the above examples like so.

# First example
chris = Person.new
home = chris.addresses.build(:person => chris)

chris.addresses.first
=> #<home>
home.person
=> #<chris>

# Second example
home = Address.new
chris = home.build_person(:addresses => [home])

home.person
=> #<chris>
chris.addresses.first
=> #<home>

I’ve occasionally used this in place of stubbing methods but am still not 100% convinced of the definite benefits one way or another. I do have some definite disadvantages of stubbing methods (nothing exciting, they’ve almost certainly been noted by many others in the past) which I’ll note down at a later date.