RSpec:如何将“let”变量作为参数传递给共享示例

时间:2018-02-02 18:23:51

标签: ruby-on-rails rspec

规范的相关片段如下:

let(:one_place) { create(:place) }
let(:other_place) { create(:place) }
let(:data) { "saved data" }

shared_examples "saves data to right place" do |right_place|
  it { expect(right_place.data).to eq data }
end

context "when something it saves to one place" do
  it_behaves_like "saves data to right place", one_place
end

context "when whatever it saves to other place" do  
  it_behaves_like "saves data to right place", other_place
end

它可以与常量参数完美配合,但在这种情况下,我收到一个错误:

  

one_place在示例组(例如describecontext块)上不可用。它仅适用于个别示例(例如it块)或来自示例范围内的构造(例如beforelet等)。

如何在这种情况下将延迟创建的变量传递给共享示例?

4 个答案:

答案 0 :(得分:4)

docs开始,我认为您需要将let语句放在传递给it_behaves_like的块中:

let(:data) { "saved data" }

shared_examples "saves data to right place" do
  it { expect(right_place.data).to eq data }
end

context "when something it saves to one place" do
  it_behaves_like "saves data to right place" do
    let(:right_place) { create(:place) }
  end
end

context "when whatever it saves to other place" do  
  it_behaves_like "saves data to right place" do
    let(:right_place) { create(:place) }
  end
end

答案 1 :(得分:1)

  

如何在这种情况下将延迟创建的变量传递给共享示例?

好旧记忆有什么不妥?

def one_place
  @one_place ||= create(:place)
end

答案 2 :(得分:1)

  1. 您也可以使用以下let变量:
  2. shared_examples 'saves data to right place' do
    
      it { expect(right_place.data).to eq data }
    
    end
    
    context 'when something it saves to one place' do
    
      let(:right_place) { create(:place) }
    
      it_behaves_like 'saves data to right place'
    
    end
    
    context 'when whatever it saves to other place' do
    
      let(:right_place) { create(:place) }
    
      it_behaves_like 'saves data to right place'
    
    end
    

    注意:仅在插值时使用双引号。

    1. 您可以将您的规格干燥如下:
    2. %w(one other).each do |location|
      
        let(:right_place) { location == one ? create(:place) : create(:place, :other) }
      
        context "when it saves to #{location} place" do
      
          it_behaves_like 'saves data to right place'
      
        end
      
      end
      

答案 3 :(得分:0)

我指出,遗憾的是,你不可能实现的目标。这是可取的,因为它使得这些变量的使用是显式的。上面提到的解决方法(定义让你使用it_behaves_like的位置)有效,但我发现这样写的共享示例令人困惑。

我使用共享示例在共享示例中明确显示所需变量:

RSpec.shared_examples "requires variables" do |variable_names|
  it "(shared example requires `#{variable_names}` to be set)" do
    variable_names = variable_names.kind_of?(Array) ? variable_names : [variable_names]
    temp_config = RSpec::Expectations.configuration.on_potential_false_positives
    RSpec::Expectations.configuration.on_potential_false_positives = :nothing

    variable_names.each do |variable_name|
      expect { send(variable_name) }.to_not raise_error(NameError)
    end

    RSpec::Expectations.configuration.on_potential_false_positives = temp_config
  end
end

像这样使用:

RSpec.shared_examples "saves data to right place" do
  include_examples "requires variables", :right_place

  # ...
end

context "..." do
  let(:right_place) { "" }
  it_behaves_like "saves data to right place"
end