在编写规范时,我经常会有一个昂贵的操作,我想测试多个方面而不需要每次都调用它。我怎么做,同时仍然引用更大的范围变量?
describe Hq::UsersController
let(:create_params) {
{'name': 'Bob',
'email': 'bob@burgers.com'}
}
describe "#create" do
context "when a user does not already exist" do
before(:context) do
# (some expensive operation here)
VCR.use_cassette('external_user_check') do
# note: this will error out, see message below
post :create, :params => create_params
end
end
it "creates the user and dependent objects" do
expect(User.count).to be(1)
user = User.first
expect(user.name).to eq(create_params['name'])
end
it "returns an 204 (no content) status" do
expect(response).to have_http_status(:no_content)
end
end
context "when a user already exists" do
before(:context) do
User.create(email: create_params['email'])
end
it "raises a RecordInvalid error and does not create any objects" do
VCR.use_cassette('external_user_check') do
expect { post :create, :params => create_params }.to raise_error(ActiveRecord::RecordInvalid)
end
# I wish I could break this into two `it` blocks :(
expect(User.count).to be(0)
end
end
end
end
这是我得到的错误:
`let` and `subject` declarations are not intended to be called
in a `before(:context)` hook, as they exist to define state that
is reset between each example, while `before(:context)` exists to
define state that is shared across examples in an example group.
我理解警告的意图,但在我的情况下,我们如何只运行或缓存一次昂贵的操作,同时还重复使用跨上下文的某些共享状态?通常,当我编写规范时,我认为状态在上下文中是相同的。
现在,似乎我唯一的解决方案是将params复制并粘贴到多个context
块中,以确保这一点。但是,如果参数变化或者参数冗长,维持成本会很高。
我愿意重构建议,或者这是否表明某些规范代码有异味。谢谢!