Как проверить Mongoid :: Observer с помощью rspec - PullRequest
8 голосов
/ 22 ноября 2011

В простой модели данных 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

Какой может быть лучший способ проверить это поведение?

1 Ответ

7 голосов
/ 25 ноября 2011

У меня есть рабочая автономная адаптация вашего кода (см. Ниже).Мне нужно было сделать три небольших изменения, чтобы заставить его работать так, как вы ожидали.

Чтобы заставить Обозревателя работать вообще, вам нужно создать его экземпляр.В моем примере мне нужно было добавить строки:

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
...