Reputation: 3568
I've tried multiple ways of getting the data I need within my shared specs, however I always get undefined values.
I am doing something similar to the following:
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
I've tried the following:
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
And doing:
it_should_behave_like "an array of hashes" do
let(:array) { totals.inactive_users }
end
before(:each) { @array = totals.inactive_users }
Then
it_should_behave_like "an array of hashes" do
let(:array) { @array }
end
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
Then
it_should_behave_like "an array of hashes", @array
All of the following results in nil
pointer exceptions and undefined variables.
Any advice, suggestions or recommendations are welcomed, thanks in advance.
Okay, so I've been looking deeper into let()
and am realizing that data passed to a shared example has to existing before the transactional block.
I'm pretty sure this was my issue as I was using before(:each)
and let()
to pass data, however those are both undefined until we reach the example group.
Input is still very much welcomed, especially on alternatives or perspectives to help get these common specs into a shared example.
Upvotes: 3
Views: 1958
Reputation: 3610
I must admit I was confused by use of rspec shared_examples and gave up on them the last time I tried to work with them, but your question inspired me to have another look.
Surprisingly it actually turned out to be very straightforward and didn't take too long at all to knock up some tests that passed - I'm either missing something fundamental in your question or the following should give you some hint at what you need to do.
The tests themselves should be self-explanatory:
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
There should be no reason why the following shouldn't work either:
it_should_behave_like 'an array of hashes' do
let(:array) { totals.inactive_users }
end
Upvotes: 2