RSpec共享示例 - 将数据传递到共享规范

时间:2016-10-13 15:23:01

标签: ruby-on-rails ruby rspec

我已经尝试了多种方法来获取我在共享规范中所需的数据,但是我总是得到未定义的值。

我正在做类似以下的事情:

require 'spec_helper'

describe UserAnalyticsService do

  before(:each) { @user = FactoryGirl(:user) }

  let(:user_query) { UserAnalyticsQuery.build(@user) }
  let(:totals) { UserAnalyticsService.new(user_query) }

  it_should_behave_like "an array of hashes" # What I want
end

我尝试过以下方法:

嵌套let()

shared_examples "an array of hashes" do
  it { expect(array).to be_an_instance_of(Array) }
  it "each element should be an instance of Hash" do
    array.each { |element| expect(element).to be_an_instance_of(Hash) }
  end
end

并且正在做:

使用let()

it_should_behave_like "an array of hashes" do
  let(:array) { totals.inactive_users }
end

使用实例变量

before(:each) { @array = totals.inactive_users }

然后

it_should_behave_like "an array of hashes" do
  let(:array) { @array }
end

Block Params

shared_examples "an array of hashes" do |array|
  it { expect(array).to be_an_instance_of(Array) }
  it "each element should be an instance of Hash" do
    array.each { |element| expect(element).to be_an_instance_of(Hash) }
  end
end

然后

it_should_behave_like "an array of hashes", @array

所有以下结果都会导致nil指针异常和未定义的变量。

欢迎任何建议,建议或建议,谢谢。

修改

好的,所以我一直在深入研究let()并意识到传递给共享示例的数据必须在事务块之前存在。

我非常确定这是我的问题,因为我使用before(:each)let()来传递数据,但是在我们到达示例组之前,这些都是未定义的。

仍然非常欢迎输入,特别是关于帮助将这些常见规范纳入共享示例的替代方案或观点。

1 个答案:

答案 0 :(得分:1)

我必须承认我对使用rspec shared_examples感到困惑,并且在我最后一次尝试使用它们时放弃了它们,但是你的问题让我有了另一种看法。

令人惊讶的是,它实际上变得非常简单,并且没有花费太长时间来敲除一些通过的测试 - 我要么在你的问题中遗漏了一些基本内容,要么以下内容会给你一些提示需要做的。

测试本身应该是不言自明的:

require 'rails_helper'

RSpec.describe Array, type: :class do
  shared_examples 'an array of hashes' do
    it { expect(array).to be_an_instance_of(Array) }

    it 'each element should be an instance of Hash' do
      array.each { |element| expect(element).to be_an_instance_of(Hash) }
    end
  end

  describe 'with an array of hashes' do
    context 'with predefined array' do
      let(:hash) { Hash.new(name: 'hash', value: 'value') }
      let(:array) { [hash, hash, hash] }

      context 'without using shared examples' do
        it { expect(array).to be_an_instance_of(Array) }

        it 'each element should be an instance of Hash' do
          array.each { |element| expect(element).to be_an_instance_of(Hash) }
        end
      end

      context 'using shared examples' do
        it_should_behave_like 'an array of hashes'
      end
    end

    context 'when passing array to shared example' do
      let(:hash) { Hash.new(name: 'hash', value: 'value') }
      let(:myarray) { [hash, hash, hash] }

      it_should_behave_like 'an array of hashes' do
        let(:array) { myarray }
      end

      context 'with use of before(:each) block' do
        before(:each) do
          @myarray = myarray
        end

        it_should_behave_like 'an array of hashes' do
          let(:array) { @myarray }
        end
      end
    end
  end
end

以下任何一项都不应该有效:

it_should_behave_like 'an array of hashes' do
  let(:array) { totals.inactive_users }
end