Writing a spec for an observer that triggers a mailer
I'm writing a simple comment observer which triggers a mailer whenever a new comment is created. All the relevant code is in this gist: https://gist.github.com/c3234352b3c4776ce132
Note that the specs for Notification
pass, but the specs for CommentObserver
fail because Notification.new_comment
is returning nil
. I found that I could get a passing spec by using this instead:
describe CommentObserver do
it "sends a notification mail after a new comment is created" do
Factory(:comment)
ActionMailer::Base.deliveries.should_not be_emp开发者_运维问答ty
end
end
This is not ideal, however, because it tests the behavior of the mailer in the observer's spec, when all I really want to know is that it's triggering the mailer correctly. Why is the mailer returning nil
in the original version of the spec? What is the best approach for speccing this type of functionality? I'm using Rails 3 and RSpec 2 (and Factory Girl, if that matters).
for context:
class CommentObserver < ActiveRecord::Observer
def after_create(comment)
Notification.new_comment(comment).deliver
end
end
# spec
require 'spec_helper'
describe CommentObserver do
it "sends a notification mail after a new comment is created" do
@comment = Factory.build(:comment)
Notification.should_receive(:new_comment).with(@comment)
@comment.save
end
end
In this case you want to check that deliver
is called on the Notification, so that's where the expectation should go. The rest of the spec code is there to set up the expectation and trigger it. Try it this way:
describe CommentObserver do
it "sends a notification mail after a new comment is created" do
@comment = Factory.build(:comment)
notification = mock(Notification)
notification.should_receive(:deliver)
Notification.stub(:new_comment).with(@comment).and_return(notification)
@comment.save
end
end
Why is the mailer returning nil in the original version of the spec?
I believe this is because message expectations act like stubs -- if no value is specified in .and_return()
or by passing in a block, should_receive
returns nil
.
精彩评论