如何在RSpec测试中实现依赖注入?解决代码块注入报错
解决RSpec共享示例中块注入的LocalJumpError问题
你遇到的LocalJumpError: no block given (yield)是因为RSpec的shared_examples不会自动捕获你传给it_behaves_like的块——普通Ruby方法的yield逻辑在这里不适用,RSpec有自己的上下文作用域规则。要实现你想要的"依赖注入",也就是把特定场景的代码注入到共享示例的登录成功上下文里,可以用显式传递块并在目标上下文里执行的方式。
正确实现方式
1. 修改共享示例,显式接收并执行块
首先调整action requiring proper user logged in to be successful共享示例,让它接收块参数,并在登录成功的上下文里执行这个块:
RSpec.shared_examples "action requiring proper user logged in to be successful" do |action, &block| context "- when the required logged user is logged in" do # 先统一处理登录逻辑(这里根据你的实际需求调整,比如登录指定的required_user) before(:each) do login(required_user) end # 执行传入的自定义场景代码 instance_eval(&block) if block_given? 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
2. 调用共享示例时传入自定义块
在changing status共享示例里,保持你原来的块写法即可,现在块会被正确传递并注入到登录成功的上下文里:
RSpec.shared_examples "changing status" do |arguments| # ... 你的其他前置逻辑 ... it_behaves_like "action requiring proper user logged in to be successful", action do 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
为什么这个方案可行?
- 我们通过
&block把块显式作为参数传递给共享示例,避免了RSpec作用域导致的块丢失问题。 instance_eval(&block)会在- when the required logged user is logged in这个上下文的作用域里执行块内容,这样块里的所有context和it都会被嵌套到这个成功登录的上下文下面,完美实现了你想要的逻辑分离和复用。- 登录逻辑被统一放在共享示例里,保证了所有复用这个示例的测试都遵循相同的登录前置条件,避免重复代码。
内容的提问来源于stack exchange,提问作者Karol Selak
相关产品推荐
相关产品推荐

