Reputation: 317
I'm just learning to write specs in ruby, and rails. So I do have two similar models that act similar when voted: question and answer. So I try to not duplicate code and write shared example for this two.
RSpec.shared_examples_for 'User Votable' do
let!(:user){ create :user }
let!(:sample_user){ create :user }
let!(:vote){ create :vote, user: user, votable: votable, vote_field: 1}
it 'user different from resource user is accapteble' do
expect(votable.user_voted?(sample_user)).to be_falsy
end
it 'user similar to resource user is accapteble' do
expect(votable.user_voted?(user)).to be_truthy
end
end
And a test itself
describe 'user_voted?' do
def votable
subject{ build(:question)}
end
it_behaves_like 'User Votable'
end
The last it in this spec fails( I think because of subject - it does not change when I create a vote) So I would be very happy if I could manage and understand how to do it right way. And very thankful for any advice
Also when I try to use mock like this, it complains on not having primary key
allow(:question){create :question}
Failures:
1) Question user_voted? behaves like User Votable user similar to resource user is accapteble Failure/Error: expect(votable.user_voted?(user)).to be_truthy
expected: truthy value
got: false
Shared Example Group: "User Votable" called from ./spec/models/question_spec.rb:23
Upvotes: 0
Views: 99
Reputation: 27374
You actually don't need to use subject
, you can just set whatever context you want using let
and it will be available within the block:
describe 'user_voted?' do
let(:votable) { build(:question) }
it_behaves_like 'User Votable'
end
Then you can just refer to votable
within your shared example and it will be defined by the context:
RSpec.shared_examples_for 'User Votable' do
let!(:user) { create :user }
let!(:sample_user) { create :user }
let!(:vote) { create :vote, user: user, votable: votable, vote_field: 1 }
it 'user different from resource user is acceptable' do
expect(votable.user_voted?(sample_user)).to be_falsy
end
it 'user similar to resource user is acceptable' do
expect(votable.user_voted?(user)).to be_truthy
end
end
You can also incidentally pass parameters into the it_behaves_like
block for more flexibility.
Ref: Providing context to a shared group using a block
(Note: fixed some spelling typos above.)
Upvotes: 1
Reputation: 19938
Instead of having a votable
method could you set the subject
as such:
it_behaves_like 'User Votable' do
subject { build(:question) }
end
Upvotes: 1