你用错了这些东西,我理解你的沮丧。所以让我给你一份简明的使用手册let
RSpec 中的 s。
主要使用价值let
并非来自节省的处理能力。它是更广泛的 RSpec 理念不可或缺的一部分。我会尽力解释,希望你会更容易进步......
let
is lazy
当且仅当它在规范中实际使用时,您在块内定义的任何内容都会被调用:
context do
let(:foo) { sleep(10000) } # will not happen
specify { expect(1).to eq(1) }
end
context do
specify do
foo = sleep(10000) # you'll wait
expect(1).to eq(1)
end
end
Use let!
,这是急切的(即不是懒惰的)版本let
let
已被记忆
块内定义的任何内容都只会发生一次(在上下文范围内):
context do
let(:random_number) { rand }
specify do
expect(random_number).to eq(random_number) # will always pass
end
end
如果您不需要此功能,请定义一个方法:
context do
def random_number
rand
end
specify do
expect(random_number).to eq(random_number) # sometimes pass, mostly fail
end
end
let
在较低级别的上下文中覆盖let
更高层次的定义:
context do
let(:x) { 1 }
specify { expect(x).to eq(1) # pass
context 'with different x' do
let(:x) { 2 }
specify { expect(x).to eq(2) # pass
end
context do
specify { expect(x).to eq(1) # pass
end
end
^ 这允许您以某种方式编写规范,其中仅在上下文中提到设置的相关“部分”,例如:
context do
let(:x) { 1 }
let(:y) { 1 }
let(:z) { 1 }
specify { expect(foo(x, y, z)).to eq(3) }
context 'when z is nil'
let(:z) { nil }
specify { expect(foo(x, y, z)).to raise_error) } # foo doesn't work with z = nil
end
context 'when x is nil'
let(:x) { nil }
specify { expect(foo(x, y, z)).to eq(15) }
end
end
Bonus: subject
是一个魔法let
# writing
subject { foo(x) }
# is almost the same as writing
let(:subject) { foo(x) }
subject
是 RSpec 中的保留概念,它是“您测试的东西”,因此您可以使用 `foo(x, y, z) 编写示例,如下所示:
context do
let(:x) { 1 }
let(:y) { 1 }
let(:z) { 1 }
subject { foo(x, y, z) }
specify { expect(subject).to eq(3) }
context 'when z is nil'
let(:z) { nil }
specify { expect(subject).to raise_error) } # foo doesn't work with z = nil
end
context 'when x is nil'
let(:x) { nil }
specify { expect(foo(subject)).to eq(15) }
end
end
关于您遇到的错误...
let
and subject
声明不打算被调用
Abefore(:context)
钩子,因为它们的存在是为了定义状态
在每个示例之间重置,同时before(:context)
存在于
定义在示例组中的示例之间共享的状态。
你正在做类似的事情
before do
let(:x) { ... }
end
只是不这样做,你定义let
inside describe
and context
,但您可以在内部使用它们(不是定义它们,而是使用定义的内容)before
and specify
:
let(:name) { 'Frank' }
before do
User.create name: name
end
specify do
expect(User.where(name: name).count).to eq(1)
end