Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing ActionMailer in Rspec

Salutations!
I'm trying to test a controller method with Rspec that looks like this:

def email_customer
  @quote = Quote.find(params[:quote_id])
  hash = {
    quote: @quote,
    body: params[:email_body],
    subject: params[:email_subject]
  }
  QuoteMailer.email_customer(hash).deliver
  redirect_to edit_quote_path params[:quote_id]
end

And the corresponding spec looks like this:

describe 'POST email_customer' do
  let!(:quote) { create(:valid_quote) }
  it 'assigns the quote and sends the customer an email' do
    post :email_customer, quote_id: quote.id
    expect(assigns(:quote)).to eq(quote)
    expect(QuoteMailer).to receive(:email_customer).with(an_instance_of(Hash)).and_return( double('QuoteMailer', deliver: true))
  end
end

When the test runs though, I get this message:

Failure/Error: expect(QuoteMailer).to receive(:email_customer).with(an_instance_of(Hash)).and_return( double('QuoteMailer', deliver: true))
       (<QuoteMailer (class)>).email_customer(an instance of Hash)
           expected: 1 time with arguments: (#<RSpec::Matchers::AliasedMatcher:0x0000000c2b1e28 @description_block=#<Proc:0x00000009816268@/home/david/.rvm/gems/ruby-2.1.1/gems/rspec-expectations-3.0.0.beta2/lib/rspec/matchers.rb:231 (lambda)>, @base_matcher=#<RSpec::Matchers::BuiltIn::BeAnInstanceOf:0x0000000c2b1e50 @expected=Hash>>)
           received: 0 times with arguments: (#<RSpec::Matchers::AliasedMatcher:0x0000000c2b1e28 @description_block=#<Proc:0x00000009816268@/home/david/.rvm/gems/ruby-2.1.1/gems/rspec-expectations-3.0.0.beta2/lib/rspec/matchers.rb:231 (lambda)>, @base_matcher=#<RSpec::Matchers::BuiltIn::BeAnInstanceOf:0x0000000c2b1e50 @expected=Hash>>)
     # ./spec/controllers/quotes_controller_spec.rb:28:in `block (3 levels) in <top (required)>'

I've scattered puts statements throughout the controller method as well as the email_customer method so I know that it ends up running its course and using the right method, but I'm not sure why its failing this. I'm guessing its a stupid syntax error that I'm not sure about. Thanks in advance for your help!

like image 589
davidicus Avatar asked Jul 23 '14 19:07

davidicus


1 Answers

Message expectations should appear before the call to the method you want to test, since they actually stub the message in the object:

describe 'POST email_customer' do
  let!(:quote) { create(:valid_quote) }
  it 'assigns the quote and sends the customer an email' do
    expect(QuoteMailer).to receive(:email_customer).with(an_instance_of(Hash)).and_return( double('QuoteMailer', deliver: true))

    post :email_customer, quote_id: quote.id

    expect(assigns(:quote)).to eq(quote)
  end
end
like image 72
Uri Agassi Avatar answered Nov 02 '22 11:11

Uri Agassi