Testing the Notifier class with Rspec

Posted on Apr 8, 2012

Today, I needed to spec the Notifier (mailer) class in a Rails project.

I don’t mean to spec the view, I just needed to test if the Notifier class method was being called with some params.

For example, I had this user story

As a User

When I am an owner of an issue

And the issue status changes

I want to get an email

So, all I had to to in my spec, is to test if the Notifier class was being called, I am testing the view in the notifier_spec, so no need to test it twice.

So, I wrote this code.

Notifier.should_receive(:issue_status_change).with(@main_user, Issue.first)
view raw issue_spec.rb hosted with ❤ by GitHub

When I ran the spec, I was surprised to see this error:

Failures:
1) Issue Notifications status change should notify users with the bitmask on
Failure/Error: issue.update_attributes(:status => 1)
NoMethodError:
undefined method `deliver' for nil:NilClass
# ./app/models/issue_observer.rb:59:in `block in after_update'
# ./app/models/issue_observer.rb:52:in `after_update'
# ./spec/models/issue_spec.rb:60:in `block (4 levels) in <top (required)>'
view raw shell_result.sh hosted with ❤ by GitHub

After scratching my head for a while, I realized that since I used mocks and expectations for the Notifier class, the underlying code was never called, so it wasn’t returning the Mail::Message class.

I fixed it by doing this:

Notifier.should_receive(:issue_status_change).with(@main_user, Issue.first).and_return(double("mailer",
:deliver => true))
view raw issue_spec.rb hosted with ❤ by GitHub

And now I have a happy spec file, that is only testing the messages between the classes, which is what I wanted to do in the first place.