惰性评估和 rspec 的 let 方法

lazy evaluation and rspec's let method

我正在读 Rails 4 Way 这本书,我正在学习 Rspec。我知道惰性求值是在使用表达式之前不求值,而急切求值是立即求值表达式。 let 使用惰性求值,在使用 let 变量之前不会执行块中的表达式。并且 let! 使用急切求值。

不过,我对rspec中的letlet!还是有点疑惑。让我们以下面的例子为例,来自书中:

describe BlogPost do
  let(:blog_post) { BlogPost.create title: 'Hello' } 
  let!(:comment) { blog_post.comments.create text: 'first post' }

  describe "#comment" do 
    before do    
      blog_post.comment("finally got a first post") 
    end  

    it "adds the comment" do 
      expect(blog_post.comments.count).to eq(2)
    end 
  end
end

作者是这样说的:

Since the comment block would never have been executed for the first assertion if you used a let definition, only one comment would have been added in this spec even though the implementation may be working. By using let! we ensure the initial comment gets created and the spec will now pass.

我以为用 let 会创建两个评论,用 let! 会创建三个评论。为什么?因为使用 let,该块不会被执行,所以不会在那里创建注释。然而,comment 将在 before 块中被惰性评估,所以现在我们有一个评论。然后将在 "adds the comment" 块中再次评估评论块,因此将创建两个评论。既然让!立即评估,因此将创建 3 个评论,而不是两个。

我误会了什么?

您看到了惰性 comment 方法的调用,其中有 none.

However, comment will be lazy evaluated in the before block

不,您向我们展示的 before 块与 let(:comment).

无关

使用 blog_post.comment 与 Rspec 或 let 无关。它使用的方法 comment 在您的 BlogPost 模型中定义。

Then the comment block will be evaluated again in the "adds the comment" block

同样,不,在该块内没有任何 comment 的调用。唯一接近的是 blog_post.comments、comments 复数,而不是评论,那是在你的模型上访问 has_many 关系。

调用 let(:comment) 定义的 comment 的唯一方法是使用 单词 comment。具有相同名称但属于不同对象的方法不相关。