How to test Mongoid :: Observer using rspec

In a simple mongoid data model with a user having many comments, I want to reward the user with a specific icon when he writes at least 1 comment. Therefore, I created an observer as follows:

class CommentBadgeObserver < Mongoid::Observer observe :comment def after_create(comment) CommentBadge.check_conditions_for(comment.user) end end class CommentBadge < Badge def self.check_conditions_for(user) if user.comments.size > 1 badge = CommentBadge.create(:title => "Comment badge") user.award(badge) end end end 

User.award method:

 def award(badge) self.badges << badge self.save end 

The following test fails (but I think this is normal, because observers are running in the background?)

 it 'should award the user with comment badge' do @comment = Factory(:comment, :user => @user) @user.badges.count.should == 1 @user.badges[0].title.should == "Comment badge" end 

What could be the best way to test this behavior?

+8
ruby ruby-on-rails observer-pattern mongoid rspec
source share
1 answer

I have a standalone adaptation of your code (see below). I had to make three small changes to make it work as you expected.

To make Observer work at all, you must create it. In my example, I needed to add the lines:

 Mongoid.observers = CommentBadgeObserver Mongoid.instantiate_observers 

In Rails, you can achieve the same by adding this to config / application.rb (as per docs ):

 config.mongoid.observers = :comment_badge_observer 

I think that CommentBadge.check_conditions_for has a small logical error, > 1 should be > 0 .

Finally, I changed the User#award method to save the icon, not the user, because the foreign key field in which the relationship is stored is on the side of the icon.

 class Comment include Mongoid::Document field :name belongs_to :user end class CommentBadgeObserver < Mongoid::Observer observe :comment def after_create(comment) CommentBadge.check_conditions_for(comment.user) end end class Badge include Mongoid::Document field :title belongs_to :user end class CommentBadge < Badge def self.check_conditions_for(user) if user.comments.size > 0 badge = CommentBadge.create!(:title => "Comment badge") user.award(badge) end end end class User include Mongoid::Document field :first_name has_many :comments has_many :badges def award(badge) self.badges << badge badge.save! end end Factory.define(:user) do |u| u.first_name 'Bob' end Factory.define(:comment) do |c| c.name 'Some comment...' end # Observers need to be instantiated Mongoid.observers = CommentBadgeObserver Mongoid.instantiate_observers describe CommentBadgeObserver do it 'should create badges' do @user = Factory.build(:user) @comment = Factory(:comment, :user => @user) @user.badges.count.should == 1 @user.badges[0].title.should == "Comment badge" end end 
+7
source share

All Articles