如何使用 rspec 测试 Mongoid::Observer

发布于 2024-12-17 15:22:24 字数 864 浏览 0 评论 0原文

在一个具有许多评论的用户的简单 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

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

On a simple mongoid data model with a user that has many comments, I want to award the user with a specific badge when he writes at least 1 comment. So I set up an observer like this :

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

The user.award method :

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

The following test fails (but I guess it is normal because observers are executed in 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 validate this behavior ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

物价感观 2024-12-24 15:22:24

我已经对您的代码进行了有效的独立改编(见下文)。我必须进行三个小更改才能使其按照您期望的方式工作。

为了让观察者正常工作,你必须实例化它。在我的示例中,我需要添加以下行:

Mongoid.observers = CommentBadgeObserver
Mongoid.instantiate_observers

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

config.mongoid.observers = :comment_badge_observer

我认为 CommentBadge.check_conditions_for 中也存在一个小逻辑错误,> 1 应该是 > 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

I have got a working stand-alone adaptation of your code (see below). I had to make three small changes to get it working the way you were expecting.

To get the Observer working at all you have to instantiate it. In my example I needed to add the lines:

Mongoid.observers = CommentBadgeObserver
Mongoid.instantiate_observers

In Rails you can achieve the same thing adding this to config/application.rb (according to the docs):

config.mongoid.observers = :comment_badge_observer

I think there is also a small logic error in CommentBadge.check_conditions_for, the > 1 should be > 0.

Finally I changed the User#award method to save the badge rather than the user, because the 'foreign key' field that stores the relationship is on the badge side.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文