3
\$\begingroup\$

How would you DRY up this RSpec code?

require "spec_helper"

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }
  subject(:mail) { InvoiceMailer.issue(student, body) }

  describe "issue" do
    subject(:mail) { InvoiceMailer.issue(student, body) }

    it "renders the subject" do
      expect(mail.subject).to eq "New Invoice!"
    end

    it "renders the receiver email" do
      expect(mail.to).to eq [student.user.email]
    end

    it "renders the sender email" do
      expect(mail.from).to eq ["info@test.com"]
    end
  end

  describe "rescind" do
    subject(:mail) { InvoiceMailer.rescind(student, body) }

    it "renders the subject" do
      expect(mail.subject).to eq "Invoice Rescinded!"
    end

    it "renders the receiver email" do
      expect(mail.to).to eq [student.user.email]
    end

    it "renders the sender email" do
      expect(mail.from).to eq ["info@test.com"]
    end
  end

end
\$\endgroup\$
4
\$\begingroup\$

You can use the its syntax:

require "spec_helper"

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }

  describe "issue" do
    subject { InvoiceMailer.issue(student, body) }

    its(:subject) { should eq "New Invoice!" }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["info@test.com"] }
  end

  describe "rescind" do
    subject { InvoiceMailer.rescind(student, body) }

    its(:subject) { should eq "Invoice Rescinded!" }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["info@test.com"] }
  end

end

You can further DRY it up using example groups

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }

  shared_examples_for "outgoing mail" do |method, mail_subject|
    subject { InvoiceMailer.send(method, student, body) }

    its(:subject) { should eq mail_subject }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["info@test.com"] }
  end

  describe "issue" do
    it_should_behave_like "outgoing mail", :issue, 'New Invoice!'
  end

  describe "rescind" do
    it_should_behave_like "outgoing mail", :rescind, 'Invoice Rescinded!'
  end
end
\$\endgroup\$
  • \$\begingroup\$ Thanks for this answer! I don't usually like its but in this case it's very readable. I feel like there is still a lot of duplication between the the issue and rescind describe blocks though. The only differences between the two are the methods on InvoiceMailer and the subject. Any thoughts? \$\endgroup\$ – niftygrifty Feb 25 '14 at 2:34
  • \$\begingroup\$ Added an option with example groups \$\endgroup\$ – Uri Agassi Feb 25 '14 at 7:15
  • \$\begingroup\$ Oh! That's exactly what I was looking for! \$\endgroup\$ – niftygrifty Feb 25 '14 at 11:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.