Rspec with ActionMailer and .deliver

I’m in the process of migrating from Rails 2 with rspec 1 to Rails 3
with
rspec 2, the process has been going pretty well, however, today I came
across an issue that I wanted to share.

I have a controller that sends out an email through a mailer.

Rails 2
code:
CurriculumCommentMailer.deliver_comment_update(@curriculum_comment,
“created”)
Rails 3 code:
CurriculumCommentMailer.comment_update(@curriculum_comment,
“created”).deliver

In my controller spec, I test to see if the email was sent out.

Rspec 1
it “emails the comment” do
CurriculumCommentMailer.should_receive(:deliver_comment_update)
post :create, :curriculum_comment =>
@curriculum_comment.attributes
end

Rspec 2
In my opinion, I expected the following code to work
it “emails the comment” do
CurriculumCommentMailer.should_receive(:comment_update)
post :create, :curriculum_comment =>
@curriculum_comment.attributes
end

However it does not. Since I’m calling should_receive on an object that
isn’t a stub/mock/double, I expected should_receive to call the
underlying
code, it does not so .deliver is called on a NilClass. (undefined method
`deliver’ for nil:NilClass)

The following code does work
mailer = double(“mailer”)
mailer.stub(:deliver)

CurriculumCommentMailer.should_receive(:comment_update).and_return(mailer)

Whereas I expected this code to work, but it does not either

CurriculumCommentMailer.should_receive(:comment_update).and_return(double(“mailer”).stub(:deliver))

thanks for your advice,

Todd

On 27 July 2011 18:09, Todd S. [email protected] wrote:

post :create, :curriculum_comment =>

isn’t a stub/mock/double, I expected should_receive to call the underlying
code, it does not so .deliver is called on a NilClass.(undefined method
`deliver’ for nil:NilClass)

You’re right – #should_receive stubs out the object’s underlying
code, so it never gets called.

The following code does work
mailer = double(“mailer”)
mailer.stub(:deliver)

CurriculumCommentMailer.should_receive(:comment_update).and_return(mailer)
Whereas I expected this code to work, but it does not either

CurriculumCommentMailer.should_receive(:comment_update).and_return(double(“mailer”).stub(:deliver))

That’s odd – I would expect that second version to work if the first
version is working. What error did you get? Was it the same “undefined
method `deliver’ for nil:NilClass” as before?

Chris

On 16 Aug 2011, at 17:30, Jason R. wrote:

But, I changed the test to this and it works fine:

CurriculumCommentMailer.should_receive(:comment_update).and_return(double(“mailer”,

:deliver => true))

Ah, of course! Because #stub doesn’t return the object whose method
you’re stubbing, it returns a message expectation. I should have spotted
that

Chris

Chris M. wrote in post #1014770:

CurriculumCommentMailer.should_receive(:comment_update).and_return(double(“mailer”).stub(:deliver))

That’s odd – I would expect that second version to work if the first
version is working. What error did you get? Was it the same “undefined
method `deliver’ for nil:NilClass” as before?

It was giving this error:
NoMethodError: undefined method `deliver’ for
#RSpec::Mocks::MessageExpectation:0x10542bb88

But, I changed the test to this and it works fine:
CurriculumCommentMailer.should_receive(:comment_update).and_return(double(“mailer”,
:deliver => true))

-Jason