懒惰的评估和rspec的let方法

时间:2015-06-05 23:30:06

标签: ruby-on-rails ruby rspec

我正在阅读The 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

作者说:

  

由于注释块永远不会被执行   断言如果使用了let定义,则只有一个注释   已添加到此规范中,即使实现可能正在运行。   通过使用让!我们确保创建初始评论和规范   现在将通过。

我认为,使用let,会创建两个注释,并且使用let!,会创建三个注释。为什么?因为使用let,块不会被执行,所以没有在那里创建注释。但是,注释将在之前的块中进行延迟评估,所以现在我们有一个注释。然后将在“添加注释”块中再次评估注释块,因此将创建两个注释。自从!立即评估,因此将创建3条评论,而不仅仅是两条评论。

我在这里误解了什么?

1 个答案:

答案 0 :(得分:0)

您看到了懒惰comment方法的调用,但没有。

  

但是,评论将在前一栏

中进行延迟评估

不,您向我们展示的前一栏与let(:comment)无关。

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

  

然后将在&#34中再次评估评论块;添加评论"块

同样,不,在该块中没有comment的任何调用。唯一关闭的是blog_post.comments,评论 s 复数,而不是评论,这样就可以访问模型上的has_many关系。

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