我正在重构我的测试。我心想,我应该将负责处理正确用户登录的逻辑和成功行为的逻辑分开。因此,我开始用我不成功的上下文创建一个共享示例,但我陷入了这一刻:
RSpec.shared_examples "changing status" do |arguments|
/* ... */
it_behaves_like "action requiring proper user logged in to be successful", action
context "- when the required logged user is logged in" do
before(:each) do
/* ... */
end
context "and when the reservation has an allowed status" do
/* ... */
end
context "and when the reservation has a not allowed status" do
/* ... */
end
end
end
RSpec.shared_examples "action requiring proper user logged in to be successful" do |action|
context "- when the logged in user is not the required logged user" do
before(:each) do
login(incidental_user)
end
it_behaves_like "unsuccessful attempt to change the reservation", action
end
context "- when there's no user logged in" do
it_behaves_like "unsuccessful attempt to change the reservation", action
end
end
因此,我想将上下文中的代码“当所需的登录用户登录时”
注入(inject)到我的共享示例中以使其干净。我尝试使用匿名代码块和 yield
关键字来做到这一点:
RSpec.shared_examples "changing status" do |arguments|
/* ... */
it_behaves_like "action requiring proper user logged in to be successful", action do
before(:each) do
/* ... */
end
context "and when the reservation has an allowed status" do
/* ... */
end
context "and when the reservation has a not allowed status" do
/* ... */
end
end
end
RSpec.shared_examples "action requiring proper user logged in to be successful" do |action|
context "- when the required logged user is logged in" do
yield
end
context "- when the logged in user is not the required logged user" do
before(:each) do
login(incidental_user)
end
it_behaves_like "unsuccessful attempt to change the reservation", action
end
context "- when there's no user logged in" do
it_behaves_like "unsuccessful attempt to change the reservation", action
end
end
但不幸的是它得到了这个错误:
LocalJumpError: no block given (yield)
那么,我该怎么做呢?
最佳答案
有趣的问题。
您可以在一个封装的示例中完成此操作,但还有另一种在我看来更清晰的方法:
为正面和负面测试创建单独的shared_example
。您已经得出了否定的结果,所以您很好(只需更改名称,以明确这是一组否定的测试)。
积极的一面可能是这样的:
RSpec.shared_examples 'restricted action with logged in user' do
before { login(authorized_user) }
specify do
expect_stuff_typical_for_logged_in_user
# e.g. expect(response).to be_success
end
end
然后在您的规范中将其包含在 include_examples
中,像这样
context do
include_examples 'restricted action with logged in user'
# you're "inside" the context of included examples so you can
# write down extra expectations specific for each action
end
可能存在这样的情况,您的积极部分没有共同的期望,只是设置上下文 - 您可以考虑使用 shared_context清楚地传达您的意图。
您可以将所有内容集中在一个共享示例中,如下所示:
RSpec.shared_examples "action requiring proper user logged in to be successful" do
# set up the context for positive scenarios, so you can include it with
# `include_examples` and be "inside" this context
before { login(authorized_user) }
context "- when the logged in user is not the required logged user" do
before(:each) do
login(incidental_user)
end
it_behaves_like "unsuccessful attempt to change the reservation"
end
context "- when there's no user logged in" do
before { log_out_people }
it_behaves_like "unsuccessful attempt to change the reservation"
end
end
这有两个问题。首先,你建立了一个积极的背景,然后你必须在消极的例子中撤销它(感觉 smelly )。 其次,规范中发生的事情可能并不明显。 它们看起来像这样:
context do
include_examples 'action requiring proper user logged in to be successful'
specify do
expect(response).not_to be_redirect
end
context 'when user have not seen changes TOS' do
before { }
specify do
expect(session[:notice]).to eq 'Please read new TOS'
end
end
而且根本不清楚负面例子是否被涵盖。
然后,如果在任何地方您需要对负面情况进行自定义期望 - 无论如何您都需要将它们分开。
您可以决定采用任何一种方式,但要注意权衡。
关于ruby-on-rails - 我可以在 RSpec 测试中实现依赖注入(inject)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50588981/