Factory Girl testing with Ruby on Rails, dependencies
I am writing some tests with RSpec for a Ruby on Rails application and am running into an issue I can't seem to figure out. I have a bunch of objects that are associated with others and I'm using Factory Girl to create them all. Here's an example of where I am having a problem:
user = Factory.create(:user)
package = Factory.build(:package, :user => user)
item = Factory.create(:item, :package => package)
All packages belong to a user, so the first dependency is rather trivial. Create a user then associate it with a package, no problem. Now here's the problem. My Package model has a validation that says it cannot be created without at least one item in the package. That means I can't use Factory.create on it. It's almost the same as doing @Package.new in my packages_controller.rb, which is fine. Later, I go on to create an item, the problem is, I cannot associate this item with the package because the package has no ID yet.
Is there anyway I can create my package, create an item and save it, then associate the two together once the 开发者_运维技巧package has an id?
Check out associations:
http://github.com/thoughtbot/factory_girl
Associated instances can be generated by using the association method when defining a lazy attribute:
Factory.define :post do |p|
# ...
p.author {|author| author.association(:user, :last_name
'Writely') } end
That way you can create the required associated item automatically.
You'll want something like:
Factory.define :package do |fac|
fac.association :item
end
That'll look for a Factory named item and try to assign it to the item= relationship.
Your validations are mutually exclusive:
My Package model has a validation that says it cannot be created without at least one item in the package
and:
(1) create my package, (2) create an item and save it, then (3) associate the two together once the package has an id?
You need to allow a package to be created in order for it to get an id. What's invalid about an empty package? Maybe there needs to be some other logic that prevents it from being used further, but it should be possible to create a package before you fill it.
If I got it right, your logic seems a little off. To have a PACKAGE, MUST have ITEM; To have ITEM, MUST have PACKAGE. Atleast one of them must be allowed to be created without the need of the other.
If this helps, here is how you create automatically a dependency on the Factory itself. In this example, Packages depends on User and Item depends on Package. The magic here is the method association.
Of course, you must have your models associtations properly done.
(First, the User Factory)
FactoryGirl.define do
factory :user do
name { "Some_Name" }
end
end
(Then, the package Factory, which depends on User)
FactoryGirl.define do
factory :package do
description { "Some_Description" }
user { association(:user) }
end
end
(Then, Item, which depends on Package)
FactoryGirl.define do
factory :item do
description { "Some_Description" }
package { association(:package) }
end
end
Hope it helps!
精彩评论