Search code examples
ruby-on-railsrubyrspecundefinedmailer

rspec failing tests with Mailer


I am getting an issue where the tests will not pass as it does not recognise user on completed_payments which is a method within the listing model. Would anyone know why this is happening?

Error is:

1) ListingMailer#sold_email Failure/Error:

Your item was bought by <%= @listing.completed_payment.user.username %> (<%= @listing.completed_payment.user.paypal_email %>) for the listed price of £<%= "%.2f" % (@listing.price_cents/100.00) %>.

ActionView::Template::Error: undefined method `user' for nil:NilClass

Files as follows:

listing_mailer.rb

class ListingMailer < ApplicationMailer
  def sold_email(listing)
    @user = listing.user
    @listing = listing
    mail(to: listing.user_email, subject: 'You have sold one of your listings')
  end

sold_email.html.erb

                        <p>Dear <%= @user.first_name %>,</p>
                        <p>Good news! You have made a sale:</p>
                        <!-- Action -->
                        <p> <%= link_to "#{@listing.version_title} by #{@listing.artist_name}", listing_url(@listing) %></p>
                        <p> Your item was bought by <strong><%= @listing.completed_payment.user.username %> (<%= @listing.completed_payment.user.paypal_email %>)</strong> for the listed price of <strong>£<%= "%.2f" % (@listing.price_cents/100.00) %></strong>.</p>
                        <p>The Paypal reference is <%= @listing.completed_payment.paypal_reference %>.</p>
                        <p>Thanks for using elvinyl,</p>
                        <p>Keith and the elvinyl team</p>

listing_mailer_spec.rb

  describe '#sold_email' do
    let(:listing) { create(:listing, :active) }
    let(:payment) { create(:payment, status: :finished, listing: listing) }
    let(:email)   { ListingMailer.sold_email(listing) }

    it { expect(email.to).to eq([listing.user_email]) }
    it { expect(email.from).to eq(ENV.fetch('EMAIL_FROM_ADDRESS')) }
    it { expect(email.subject).to eq 'You have sold one of your listings' }
  end

Thank you


Solution

  • I believe this is happening because you haven't called payment to instantiate it. Therefore, there is no payment on the listings object.

    There are a number of ways around this, you can just call payment before your expectations or do something like

    ListingMailer.sold_email(payment.listing)
    

    or, have a trait in your listings factory so that it will create a complete payment object for you. Something like create(:listing, :active, :complete_payment)