让! vs 让和之前在 Rspec



在 Rspec 中,让我们使用延迟实例化,这样let(:foo) { create(...) }在有东西调用它之前不会初始化它。通常这很好,因为它只在需要时使用,并使 rspec 测试时间更快。

但是,有时您会有一个需要该变量但没有显式调用它的规范。因此,使用延迟实例化,规范将失败。

解决方案是轰轰烈烈!let!(:foo) { create(...) }将强制初始化变量。

一些开发人员似乎非常反对这一点,并且更喜欢:

let(:foo) { create(...) } before do foo end 以强制初始化。

这有什么原因吗?这两种方法之间有什么区别吗?

我可以想到一个区别:before块会复合,你可以用let覆盖let!,反之亦然。我给你举个例子:

context do
let!(:foo) { create(:foo) }
let(:bar) { create(:bar) }
before { bar }
context do
# if in this context you wish to switch back to "lazy" versions you can
# do that for :foo, just do:
let(:foo) { create(:foo) }
# but you can't "undo" before, even if you define an empty one:
before { }
# it does not cancel the `before` blocks defined in higher contexts
end
end

编辑:我刚刚意识到这并不能真正回答为什么有人更喜欢before而不是let!的问题。也许:正如评论中提到的,顺序是不同的,但如果你依赖规格中的这种细微差别 - 它已经太复杂了。

很多情况是风格问题,开发人员并不完全了解RSpec的主要功能,很多时候人们就是没有意义。人类不是机器,特别是在时间压力下,开发人员会做他们在理想条件下不会做的事情:)。

但所呈现的两种情况并不完全相同。 例如,如果您使用的是subject,则在let!初始化之前,它会在before钩子中进行评估,而不是在it内部进行评估。我没有测试,但我相信这些情况应该显示差异:

let!(:car) { create(:car) }
let(:driver) { create(:driver) }
subject { driver.car() }
it { expect(subject).to eq car } # Fail: 

这强制car之前创建并可用于subject

let(:driver) { create(:driver) }
subject { driver.car() }
before { create(:car) }
it { expect(subject).to eq car } # Success

相关内容

  • 没有找到相关文章

最新更新