Forum: RSpec how to test arguments going into a mailer method?

Posted by Patrick Collins (patrick99e99)
on 2011-12-09 08:28
(Received via mailing list)
Hi,

So I am not really interested in testing the content of the actual body 
of an
outgoing email.  I trust that Rails' internal mechanisms work, however 
recently
I came across some code that did something that I did want to test:

---

class PaypalProcessor

  def send_email
    Notifier.paypal_error(@errors, 
@params.merge(decoded_custom_params)).deliver
  end

end

---


... I simply wanted to verify that the variables being passed into my
ActionMailer::Base subclass are exactly what I expect them to be.  I 
felt that
this is pretty much all that I need to test (other than verifying that 
the
actual email will be sent).  So I wrote the following test:


---


before :each do
  @encoded = Base64.encode64s({ :post_id => @post.id, :user_id => 
@user.id }).to_json
  @processor = PaypalProcessor.new(:params => { :custom => @encoded, 
:foo => "bar" })
end

it "sends an email to notify us of invalid data" do
  @processor.should_not be_valid

  Notifier.expects(:new).with(:paypal_error, @errors, { :post_id => 
@post.id,
                                                        :user_id => 
@user.id,
                                                        :foo => "bar",
                                                        :custom => 
@encoded })

  # note: I wrote the above expectation that way based off of what I saw 
in
  # ActionMailer::Base's code..  It uses method missing and does:
  # new(method, *args).message

  lambda { @processor.send_email }.should 
change(ActionMailer::Base.deliveries, :count).by(1)
end


---


  I get this failure:

  1) PaypalParamProcessor validation sends an email to notify us of 
invalid data
     Failure/Error: lambda { @processor.send_email }.should 
change(ActionMailer::Base.deliveries, :count).by(1)
     Mocha::ExpectationError:
       unexpected invocation: Notifier.new(:paypal_error, ['paypal did 
not verify the transaction!', 'paypal notified us of a payment with an 
invalid gross amount!', 'paypal gave a currency code other than USD!', 
'paypal shows this transaction as belonging to another business!'], 
{:post_id => 430, :user_id => 538, :foo => 'bar', :custom => 
'eyJwb3N0X2lkIjo0MzAsInVzZXJfaWQiOjUzOH0='})
       unsatisfied expectations:
       - expected exactly once, not yet invoked: 
Notifier.new(:paypal_error, nil, {:post_id => 430, :user_id => 538, :foo 
=> 'bar', :custom => 'eyJwb3N0X2lkIjo0MzAsInVzZXJfaWQiOjUzOH0='})
       satisfied expectations:
       - allowed any number of times, invoked once: #<Mock:Fancy Notify 
Object>.acknowledge(any_parameters)
       - allowed any number of times, invoked once: #<Mock:Fancy Notify 
Object>.complete?(any_parameters)
       - allowed any number of times, invoked once: #<Mock:Fancy Notify 
Object>.gross(any_parameters)
       - allowed any number of times, not yet invoked: #<Mock:Fancy 
Notify Object>.acknowledge(any_parameters)
       - allowed any number of times, invoked once: 
ActiveMerchant::Billing::Integrations::Paypal::Notification.new(any_parameters)
     # ./lib/paypal_param_processor.rb:43:in `send_email'
     # ./spec/lib/paypal_param_processor_spec.rb:63
     # ./spec/lib/paypal_param_processor_spec.rb:63

---

So, obviously my approach isn't so great.  Can anyone assist me with a 
better way to do this?

Patrick J. Collins
http://collinatorstudios.com
Posted by "Morten Møller Riis" <mortenmoellerriis@gmail.com> (Guest)
on 2011-12-09 11:52
(Received via mailing list)
How about this?

paypal_error = mock('paypal_error')
paypal_error.should_receive(:deliver)
Notifier.should_receive(:paypal_error).with(@errors, hash_including({ 
:post_id => @post.id,
                                                       :user_id => 
@user.id,
                                                       :foo => "bar",
                                                       :custom => 
@encoded })).and_yield(paypal_error)


Mvh
Morten Mller Riis
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.