一个
user
有很多 comments
,所以我想要一个工厂 user
与与之关联的 comment
(user_with_comment
):
factory :user, class: User do |t|
...
factory :user_with_comment do |t|
after(:create) do |user|
FactoryGirl.create(:comment, user_id: user.id)
end
end
它工作正常...当我调用
FactoryGirl.create(:user_with_comment)
时,它会在我的 user
中创建 comment
和相关的 test db
。
但是,我在
controller_spec
中面临一些问题:
使用
let
我必须重新加载 user
才能看到 comment
:
let(:user) { FactoryGirl.create(:user_with_comment) }
user.comments.size #=>0
user.reload
user.comments.size #=>1
一种解决方案是使用
before(:each)
,但它会在每次测试之前创建 venda
和 comment
:
before(:each) do
@user = FactoryGirl.create(:user_with_comment)
end
@user.comments.size #=>1
或者,我可以在每次测试之前重新加载
user
,但它也会命中数据库:
let(:user) { FactoryGirl.create(:user_with_comment) }
before(:each) do
user.reload
end
在这种情况下最好的方法是什么?
我在寻找有关如何重新加载 let 变量的另一个问题时看到了这一点,但在这里我认为可能的解决方案是让工厂使用关联本身而不是执行 after_create (不确定当问题出现时它是否可用)虽然被问到):
factory :user, class: User do |t|
...
factory :user_with_comment do
# might need create(:comment) but in my testing build worked
comments { [build(:comment)] }
end
end
let(:user) { FactoryGirl.create(:user_with_comment) }
user.comments.size #=> 1
这与 let 是惰性计算的并且用户工厂的注释是在创建用户后添加的这一事实有关。
请注意,let 是惰性求值的:直到第一次才求值 它定义的方法被调用。
请参阅有关 let 和 let 的 RSpec 文档!
使用let表示您在示例中第一次使用它时创建的用户,因此注释是在之后创建的。你可以使用让!在每个示例之前创建用户以避免重新加载。如果您在规范中的所有/大多数示例中使用工厂,这不会对您的测试产生负面影响。
这个怎么样?
let(:user) { FactoryGirl.create(:user_with_comment).reload }