代码之家  ›  专栏  ›  技术社区  ›  Karol Selak

我能在我的RSPEC测试中实现依赖注入吗?

  •  2
  • Karol Selak  · 技术社区  · 7 年前

    我正在重构测试。我对自己说,我应该把负责处理的逻辑和我成功行为的逻辑分开。因此,我开始创建一个与我失败的上下文共享的示例,但我陷入了这一刻:

    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
    

    所以,我想从我的上下文注入代码 "when the required logged user is logged in" 以我共同的例子让它变得清晰。我试着用匿名代码块和 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:未给定块(yield)

    那么,我该怎么做呢?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Greg    7 年前

    有趣的问题。

    你可以用一个封装的例子来做,但是还有另一个更清晰的方法:

    分开 shared_example s表示阳性和阴性。你做的是阴性的,所以你很好(只需改变名字,让它清楚地表明这是一组阴性测试)。

    正面的可以是这样的:

    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 
    

    而且还不清楚的是,负面的例子已经被覆盖了。

    然后,如果在任何地方,您需要对 消极的 不管怎样,你还是需要把它们分开。

    你可以决定走哪条路,注意权衡。

        2
  •  0
  •   Karol Selak    7 年前

    最后我用lambda解决了我的问题:

    RSpec.shared_examples "changing status" do |arguments|
      /* ... */
    
      it_behaves_like "action requiring proper user logged in to be successful", action, -> {
        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
    RSpec.shared_examples "action requiring proper user logged in to be successful" do |action, successful_behavior|
      context "- when the required logged user is logged in" do
        successful_behavior.()
      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
    
    推荐文章