RSpec: Ожидание, что модель не работает во время тестирования контроллера

Я пытаюсь написать функциональный тест. Мой тест выглядит следующим образом:

describe PostsController do
  it "should create a Post" do
    Post.should_receive(:new).once
    post :create, { :post => { :caption => "ThePost", :category => "MyCategory" } }
  end
end

Мой PostsController (фактически его часть) выглядит следующим образом:

PostController < ActiveRecord::Base

  def create
    @post = Post.new(params[:post])
  end

end

Выполняя тест, я всегда получаю сообщение об ошибке, в котором говорится, что класс Post ожидал :new, но так и не получил его. Тем не менее, фактический пост создается.

Я новичок в RSpec. Я что-то упускаю?


person gmile    schedule 29.04.2010    source источник


Ответы (2)


РЕДАКТИРОВАТЬ – удалить предыдущий мусор.

Это должно делать то, что вы хотите

require File.dirname(__FILE__) + '/../spec_helper'

describe PostsController do
  it "should create a Post" do
    attributes = {"Category" => "MyCategory", "caption" => "ThePost"}
    Post.stub!(:new).and_return(@post = mock_model(Post, :save => false))
    Post.should_receive(:new).with( attributes ).and_return @post
    post :create, { :post => attributes }
  end
end

Это предполагает, что вы используете собственную фиктивную библиотеку rspecs и что у вас установлен гем rspec_rails.

person Steve Weet    schedule 30.04.2010

Вы можете использовать метод controller Rspec-rails для проверки ожидания сообщений на контроллерах, как описано здесь. Таким образом, один из способов проверки действия create выглядит следующим образом:

describe PostsController do
  it "should create a Post" do
    controller.should_receive(:create).once
    post :create, { :post => { :caption => "ThePost", :category => "MyCategory" } }
  end
end

EDIT (приведение аргумента)

Вы можете подумать, стоит ли писать тест, зависящий от реализации действия create. Если вы тестируете что-либо, кроме надлежащих обязанностей контроллера, вы рискуете сломать тесты при рефакторинге, и вам придется возвращаться и переписывать тесты при изменении реализации.

Задача действия создания состоит в том, чтобы создать что-то, так что проверьте это:

Post.count.should == 1

и тогда вы узнаете, было ли создано сообщение, независимо от того, как оно было создано.

РЕДАКТИРОВАНИЕ №2 (гм...)

Из вашего первоначального вопроса я вижу, что вы уже знаете, что сообщение создается. Я бы по-прежнему утверждал, что вы должны тестировать поведение, а не реализацию, и что проверка того, получает ли модель сообщение, не является хорошей вещью в тесте контроллера. Может быть, вы отлаживаете, а не тестируете?

person zetetic    schedule 29.04.2010
comment
Спасибо, но это не то, чего я пытаюсь достичь. Что я хочу сделать, так это проверить, получил ли класс модели определенное сообщение (например: find,: create или около того) - person gmile; 30.04.2010