Тестирование спецификации модели, которая использует обратный вызов after_create - PullRequest
4 голосов
/ 21 октября 2010

Вот модель, которую я использую, я немного упростил ее до простейшей формы, которая все еще не соответствует моему примеру:

class User <  ActiveRecord::Base
  after_create :setup_lists

  def setup_lists
    List.create(:user_id => self.id, :name => "current")
    List.create(:user_id => self.id, :name => "master")
  end
end

И я хотел бы указать пример какследует:

require 'spec_helper'

describe User do
  before(:each) do
    @user = Factory(:user)
  end

  describe "#setup_lists" do
    before(:each) do  
     List.stub(:create).with(:name => "current")
     List.stub(:create).with(:name => "master")

     it "creates a new master list" do
        List.should_receive(:create).with(:name => "master")
     end

     it "creates a new current list" do
        List.should_receive(:create).with(:name => "current")
     end
  end
end

Что я ожидал, будет работать нормально, но у меня осталась следующая ошибка:

Failures:
  1) User#setup_lists creates a new master list
     Failure/Error: List.should_receive(:create).with(:name => "current")
     (<List(id: integer, name: string, created_at: datetime, updated_at: datetime, user_id: integer) (class)>).create({:name=>"current"})
      expected: 1 time
      received: 0 times
    # ./spec/models/user_spec.rb:44

  2) User#setup_lists creates a new current list
     Failure/Error: List.should_receive(:create).with(:name => "master")
     (<List(id: integer, name: string, created_at: datetime, updated_at: datetime,        user_id: integer) (class)>).create({:name=>"master"})
     expected: 1 time
     received: 0 times
  # ./spec/models/user_spec.rb:48

Кто-нибудь может мне помочь понять, почему это происходит?

Ответы [ 2 ]

4 голосов
/ 24 октября 2010

Три вопроса:

1) Объект User создается до установки ожидаемого сообщения, поэтому should_receive никогда не увидит сообщение;

2) Вы заглушаете методы, для которых вы также устанавливаете ожидания. Вы хотите отключить методы, для которых вы не устанавливаете ожидания, но которые необходимы для прохождения теста

3) Вам необходимо передать все параметры

Чтобы исправить, создайте объект User после установки ожидания и заглушите каждый метод по очереди (потому что ваша модель вызывает List.create дважды):

describe User do
  describe "#setup_lists" do
    it "creates a new master list" do
      List.stub(:create).with(:user_id=>1,:name => "current")
      List.should_receive(:create).with(:user_id=>1,:name => "master")
      @user = User.create
    end

    it "creates a new current list" do
      List.stub(:create).with(:user_id=>1,:name => "master")
      List.should_receive(:create).with(:user_id=>1,:name => "current")
      @user = User.create
    end
  end
end

Хотя это действительно вопрос стиля, более разумно использовать здесь настоящий объект User, а не фабрику, поскольку вы тестируете саму модель.

2 голосов
/ 14 августа 2013

Zetetic ответ потрясающий, но если вы хотите что-то немного быстрее (и все еще работает), я бы рекомендовал использовать камень shoulda-callback-matchers . Это полный набор средств сравнения, которые облегчают тестирование обратных вызовов. Я все о простом и сокращающем шаблоне. Вы можете увидеть некоторые примеры в моем скелете тестирования модели RSpec , если хотите посмотреть.

В любом случае, работа будет выполнена!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...