I have an rspec spec test that has two sets of the same tests (from 24 Pull Requests). I thought I'd refactor the spec whilst I fixed something else.
Normally I just do a basic each ... do
array to DRY things up:
require 'spec_helper'
describe ReminderMailer, type: :mailer do
# Half the code yay! :D
['daily','weekly'].each do |time_format|
describe time_format do
let(:time_format) { time_format }
let(:user) do
mock_model(User, nickname: 'David',
email: '[email protected]',
languages: ['Ruby'],
skills: [],
pull_requests: double(:pull_request, year: []),
suggested_projects: [])
end
# How do I do this bit better?
let(:mail) {
if time_format == 'daily'
ReminderMailer.daily(user)
else
ReminderMailer.weekly(user)
end
}
end
I couldn't figure out how to use the time_format with the send command, so I could do something like:
let(:mail) { ReminderMailer.send(timeformat(user) }
How could I do this?
1 Answer 1
The snippet you asked to re-write:
let(:mail) { ReminderMailer.send(time_format, user) }
Now, IMO using each
to write specs is a bad practice. Why? Because rspec already provides idiomatic infrastructure to keep specs DRYed: use before
and shared_examples
. I'd write:
describe ReminderMailer, type: :mailer do
let(:user) { ... }
shared_examples "a reminder mailer" do |subject:, body:|
it 'renders the subject' do
expect(mail.subject).to eq(subject)
end
it 'renders the receiver email' do
expect(mail.to).to eq([user.email])
end
it 'renders the sender email' do
expect(mail['From'].to_s).to eq('24 Pull Requests <[email protected]>')
end
it 'uses nickname' do
expect(mail.body.encoded).to match(user.nickname)
end
it 'contains periodicity in body' do
expect(mail.body.encoded).to match(body)
end
end
describe 'daily' do
let(:mail) { ReminderMailer.daily(user) }
it_behaves_like "a reminder mailer",
subject: '[24 Pull Requests] Daily Reminder',
body: 'today'
end
describe 'weekly' do
let(:mail) { ReminderMailer.weekly(user) }
it_behaves_like "a reminder mailer",
subject: '[24 Pull Requests] Weekly Reminder',
body: 'week'
end
end
-
\$\begingroup\$ Fantastic, even better than what I asked about :) \$\endgroup\$Peter Souter– Peter Souter2014年12月09日 20:05:28 +00:00Commented Dec 9, 2014 at 20:05
time_format
is the same as both of the method names; stackoverflow.com/questions/13810429/call-a-method-by-name. \$\endgroup\$