【问题标题】:How to test Mongoid::Observer with rspec如何使用 rspec 测试 Mongoid::Observer
【发布时间】:2011-11-22 09:20:26
【问题描述】:

在一个用户拥有许多 cmets 的简单 mongoid 数据模型上,我想在用户写下至少 1 条评论时奖励他一个特定的徽章。所以我设置了一个这样的观察者:

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 方法:

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

下面的测试失败(但我猜这是正常的,因为观察者是在后台执行的?)

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

验证此行为的最佳方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby rspec mongoid observer-pattern


    【解决方案1】:

    我已经对您的代码进行了独立的改编(见下文)。我必须进行三处小改动才能使其按您预期的方式运行。

    要让 Observer 完全正常工作,您必须实例化它。在我的示例中,我需要添加以下行:

    Mongoid.observers = CommentBadgeObserver
    Mongoid.instantiate_observers
    

    在 Rails 中,您可以通过将其添加到 config/application.rb 来实现相同的效果(根据 docs):

    config.mongoid.observers = :comment_badge_observer
    

    我认为CommentBadge.check_conditions_for中还有一个小逻辑错误,&gt; 1应该是&gt; 0

    最后我更改了User#award 方法来保存徽章而不是用户,因为存储关系的“外键”字段在徽章端。

    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
    

    【讨论】:

    • 很高兴知道,谢谢。你有没有让它在你的 Rails 中工作,是观察者实例化还是其他什么?
    • 是的,我在我的应用程序中做到了;我必须在我的规范文件中设置观察者实例化的两行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 2018-08-23
    • 2013-12-07
    • 2019-12-10
    相关资源
    最近更新 更多