更新
我又回到了使用Fixtures的状态。IMOP,fixture远比工厂好;更容易使用,更容易编写,更容易理解(没有魔力)。我的建议:将你的测试库限制在非常基础的(听DHH)...use最小的fixtures。
原文
在我的应用程序中,一个地区有许多学校,一个学校有许多用途,一个用户有许多帐户,一个帐户有一个角色。为了创建用于测试的完整工厂,我需要创建一个跨工厂的用户和学校。在我最近的尝试中,我得到了一个“堆栈级别太深”的错误。
我的user_test.rb
FactoryGirl.define do
factory :district do
name "Seattle"
end
factory :school do
association :primarycontact, factory: :user # expecting this to attach the user_id from factory :user as :primary contact_id in the school model
association :district, factory: :district # expecting this to attach the :district_id from the :district factory as :district_id in the school model
name "Test School"
end
factory :user do, aliases: [:primarycontact]
email "adam@example.com"
name "Who What"
username "wwhat"
password "123456"
password_confirmation { |u| u.password }
association :school, factory: :school # expecting this to create :school_id in the users model, using the :school factory
end
factory :role do
name "student"
end
factory :account do
association :user, factory: :user
association :role, factory: :role
end
end因此,我正在尝试使用上面工厂中的用户和角色创建一个帐户,并使用与该学区关联的学校关联的用户创建FactoryGirl.create(:account)...。这对我不起作用。在失败的测试中,我得到一个“堆栈级别太深”的错误。而且,我相信在每个新工厂之前,我的每个DatabaseCleaner.clean都会清除测试数据库。
调用这些工厂的测试是:
describe "User integration" do
def log_em_in
visit login_path
fill_in('Username', :with => "wwhat")
fill_in('Password', :with => "123456")
click_button('Log In')
end
it "tests log in" do
user = FactoryGirl.create(:account)
log_em_in
current_path.should == new_user_path
end
end。
current_path.should == new_user_path returns unknown method error 'should'如何改进此代码以正确嵌套工厂并获得current_user以便继续测试?
模型
school.rb
belongs_to :district
belongs_to :primarycontact, :class_name => "User"
has_many :users, :dependent => :destroyuser.rb
belongs_to :school
has_many :accounts, :dependent => :destroydistrict.rb
has_many :schoolsaccount.rb
belongs_to :role
belongs_to :userrole.rb
has_many :accounts
has_many :users, :through => :accounts发布于 2013-01-01 16:14:46
您的基本问题是,您的user工厂和school工厂之间存在循环依赖,这是由于您在创建学校时创建了一个primarycontact (用户),然后该用户又创建了一所学校,依此类推。
您可以通过更改在user工厂中定义school关联的方式来解决此问题。不过,在这样做之前,我建议作为一般规则使用关联的速记符号。因此,请替换以下内容:
factory :account do
association :user, factory: :user
association :role, factory: :role
end有了这个:
factory :account do
user
role
end使用这种简化,以下工厂将执行您想要的操作,而不会生成任何循环依赖:
FactoryGirl.define do
factory :district do
name "Seattle"
end
factory :school do |school|
district
primarycontact
name "Test School"
after_build do |s|
s.primarycontact.school = s
end
end
factory :user do
email "adam@example.com"
name "Who What"
username "wwhat"
password "123456"
password_confirmation { |u| u.password }
school
end
factory :primarycontact, class: "User" do
# add any attributes you want the primarycontact user to have here
end
factory :role do
name "student"
end
factory :account do
user
role
end
end请注意,我所做的是使用class: "User"选项为primarycontact创建一个工厂。与user工厂不同,此工厂在默认情况下不创建school,从而避免了循环依赖。
然后在school工厂中,我使用after_build回调将学校本身分配给primarycontact上的school协会,而不是创建一所新学校(导致您的工厂出现问题)。
希望这是有意义的。请注意,在最新版本的factory_girl中回调语法已更改,请参阅documentation了解详细信息。
https://stackoverflow.com/questions/14087972
复制相似问题