2
\$\begingroup\$

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?

asked Dec 9, 2014 at 16:57
\$\endgroup\$
1

1 Answer 1

5
\$\begingroup\$

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
answered Dec 9, 2014 at 17:55
\$\endgroup\$
1
  • \$\begingroup\$ Fantastic, even better than what I asked about :) \$\endgroup\$ Commented Dec 9, 2014 at 20:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.