I wrote this code for testing controller update function. Wrote a method for eliminating duplicate code. Is this an explicit way to do it?
users_controller_spec.rb
context 'Update failed' do
def render_edit
user.reload
expect(response.status).to eq(200)
end
it 'Name is nil' do
put :update, params: { id: user.id, user: { name: '' } }
render_edit
end
it 'Email is exist' do
create(:user, email: 'user@gmail.com')
put :update, params: { id: user.id, user: { email: 'user@gmail.com' } }
render_edit
end
it 'Email is nil' do
put :update, params: { id: user.id, user: { email: '' } }
render_edit
end
it 'Password must be at least 8 characters' do
put :update, params: { id: user.id, user: { password: '1234567', password_confirmation: '1234567' } }
render_edit
end
it 'Passwords do not match' do
put :update, params: { id: user.id, user: { password: '1234567890', password_confirmation: '123456789' } }
render_edit
end
end
I was thinking to use after(:each). But it looks a little wired in logic. Or use loop to replace params.
Any suggestion?
You can use shared examples as suggested in the comments, but there's an easier way.
context 'Update failed' do
before do
put :update, params: params
user.reload # I'm not sure why you need this
end
subject { response }
context 'Name is nil' do
let(:params} { {id: user.id, user: { name: '' }} }
it { is_expected.to be_success }
end
context 'Email exists' do
let(:params) { { id: user.id, user: { email: 'user@gmail.com' } }
let(:user) { create(:user, email: 'user@gmail.com') }
it { is_expected.to be_success }
end
# and so on
end
The main rune I use is - make it obvious what change in each context. So instead of redefining put ...
, extract it as a let and define it per context.
be_success
is part of rspec magic, wherever you use be_something
matcher it'll try to use something?
method and check if it's true, i.e.
expect(foo).to be_empty?
== expect(foo.empty?).to eq(true)
If you don't want it make it like this
subject { response.status }
# and later
is_expected.to eq 200
is_expected.to
is just a shorthand for expect(subject).to