RSpec:let和a之前的区别是什么?

在RSpec中let和a before什么区别?

何时使用每个?

下面的例子中会有什么好办法(let or before)?

 let(:user) { User.make !} let(:account) {user.account.make!} before(:each) do @user = User.make! @account = @user.account.make! end 

我研究了这个stackoverflowpost

但是如何定义像上面这样的关联的东西呢?

人们似乎已经解释了一些不同的基本方法,但在(:全部)之前被排除在外,并没有解释为什么应该使用它们。

我相信实例variables在绝大多数规范中没有被使用,部分原因是由于这个答案中提到的原因,所以在这里我不会提到它们作为一个选项。

让块

let块中的代码只在引用时执行,延迟加载意味着这些块的sorting是不相关的。 这给你一个大量的权力,减less重复设置通过您的规格。

一个(非常人为的,小的)例子是:

 let(:person) { build(:person) } subject(:result) { Library.calculate_awesome(person, has_moustache) } context 'with a moustache' do let(:has_moustache) { true } its(:awesome?) { should be_true } end context 'without a moustache' do let(:has_moustache) { false } its(:awesome?) { should be_false } end 

你可以看到has_moustache在每种情况下的定义都是不同的,但是不需要重复subject定义。 需要注意的是,将使用在当前上下文中定义的最后的let块。 这对于设置大部分规格的默认设置是很好的,如果需要的话可以覆盖。

例如,检查calculate_awesome的返回值,如果传递一个top_hat设置为true但没有胡须的person模型,将会是:

 context 'without a moustache but with a top hat' do let(:has_moustache) { false } let(:person) { build(:person, top_hat: true) } its(:awesome?) { should be_true } end 

另一个要注意的关于让块,他们不应该使用,如果你正在search的东西已被保存到数据库(即Library.find_awesome_people(search_criteria) ),因为他们不会被保存到数据库,除非他们已经引用。 let!before块应该在这里使用。

另外, 以前从来没有用过触发执行let块,这就是let! 是为了!

让!

let! 块按照它们定义的顺序执行(非常类似于之前的块)。 与之前的块之间的一个核心区别是你得到了对这个variables的明确引用,而不需要回退到实例variables。

如同let块,如果多重let! 块被定义为相同的名称,最近的是将在执行中使用。 核心的区别是let! 如果像这样使用块,将会执行多次,而let块只会执行最后一次。

之前(:每个)块

before(:each)是块之前的默认值,因此可以像before {}引用before {}而不是before(:each) {}指定完整的before(:each) {}

在一些核心情况下使用块before我个人偏好。 如果出现以下情况,我将在使用前

  • 我正在使用嘲弄,残片或双打
  • 有任何合理的大小设置(通常这是你的工厂特征没有正确设置的标志)
  • 有许多variables我不需要直接引用,但是需要进行设置
  • 我在rails中编写function控制器testing,我想执行一个特定的请求来testing(即before { get :index } )。 尽pipe在很多情况下你可以使用这个subject ,但是如果你不需要参考的话,它有时会更加明确。

如果你发现你自己的规格beforebefore写得很大,请检查你的工厂,确保你完全了解特性和灵活性。

之前(:全部)块

这些只在当前语境(及其子语)的规范之前执行过一次。 如果写得正确的话,这些可以被用来取得巨大的优势,因为在某些情况下这可以减less执行和努力。

一个例子(几乎不影响执行时间)嘲笑一个testing的ENVvariables,你应该只需要做一次。

希望帮助:)

几乎总是,我更喜欢let 。 你链接的post指出let也更快。 但是,有时候需要执行很多命令时,我可以使用before(:each)因为当涉及到很多命令时,它的语法更加清晰。

在你的例子中,我肯定会喜欢使用let而不是before(:each) 。 一般来说,当只做一些variables初始化时,我倾向于使用let

没有提到的一个很大的区别是用let定义的variables在第一次调用之前不会被实例化。 因此,虽然before(:each)块会实例化所有variables,但let我们来定义可能在多个testing中使用的许多variables,但不会自动实例化它们。 如果不知道这一点,如果您预期所有的数据都会被预先加载,您的testing可能会回来咬你自己。 在某些情况下,甚至可能需要定义一些letvariables,然后使用before(:each)块来调用每个let实例,以确保数据可用于开始。

看起来你正在使用机械师。 当心,你可能会看到一些问题,使! (非爆炸版本)发生在全局夹具事务之外(如果您也使用事务性夹具),则会损坏您的其他testing的数据。