如何重新加载由 let 定义的变量

How to reload a variable defined by let

一个 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) 时,它会在我的 test db.

中创建 user 和相关的 comment

但是,我在 controller_spec 中遇到了一些问题:

使用 let 我必须重新加载 user 才能看到 comment:

let(:user) { FactoryGirl.create(:user_with_comment) }
user.comments.size #=>0
user.reload
user.comments.size #=>1

一个解决方案是使用 before(:each),但它会在每次测试之前创建 vendacomment

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 是延迟求值的事实有关,并且在创建用户后添加了对您的用户工厂的评论。

Note that let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked.

请参阅 RSpec documentation 关于让和让!

使用 let 意味着当您在示例中第一次使用它时创建了用户,因此评论是在之后创建的。你可以使用让!在每个示例之前创建用户以避免重新加载。如果您在规范示例的 all/most 中使用工厂,这不会对您的测试产生负面影响。

这个怎么样?

let(:user) { FactoryGirl.create(:user_with_comment).reload }