Ожидания Rspec и Rails Controller

Все,

Возникли некоторые проблемы с тестом, похожие на следующие:

it "does something" do
  controller.should_receive(:some_method).once

  expect {
    post :create, some_params_hash, some_session_hash
  }.to change(Something, :count).by(1)
end

Контроллер на стороне рельсов - грубый пример:

class SomethingsController
  before_filter :some_method

  def create
    respond_with Something.create params[:something]
  end

  def some_method
    puts 'some_method'
  end
end

Это все хорошо и прекрасно работает, если я удаляю ожидание controller.should_receive. Если я оставлю ожидание на месте — тест провалится.

Странно то, что он не терпит неудачу из-за неудовлетворенного ожидания — на самом деле, похоже, он соответствует ожиданию should_receive(:some_method) — просто создание записи и последующая оценка изменения завершаются ошибкой.

Итак - вопрос:

Это правильный способ указать ожидания от контроллера, который вызывается как часть этого теста??

Спасибо за любую помощь!


person Cory    schedule 17.04.2012    source источник


Ответы (1)


Распространенная ошибка rspec заключается в том, что вы думаете, что ожидание метода, подобное установленному вашим should_receive, просто отслеживает приложение, чтобы убедиться, что определенные вещи происходят. Но на самом деле он встраивается в поток и полностью заменяет метод.

Таким образом, some_method вашего контроллера будет заменен на тот, который ничего не делает, кроме возврата nil. И фильтр перед, который возвращает nil, остановит всю обработку. Ваше действие никогда не вызывается.

Измените свое ожидание на это:

controller.should_receive(:some_method).once.and_return true

Также обратите внимание, что в вашем примере проверяются две вещи: проверка того, что ваше действие вызывает some_method, и проверка того, что количество сохраненных Somethings увеличивается на единицу. Это нормально, но если вы действительно намеревались проверить только последнее, вы могли бы использовать заглушку вместо ожидания, что немного компактнее:

controller.stub some_method: true

ОБНОВЛЕНИЕ: я должен добавить, что в последних версиях Rails возвращаемое значение фильтра контроллера игнорируется. (Фильтр может предотвратить выполнение действия, просто визуализируя что-либо.) Однако принцип should_receive rspec, заменяющий ваш метод, остается верным и общеприменимым.

person Rob Davis    schedule 17.04.2012
comment
Теперь я могу спать по ночам. Спасибо. - person Cory; 18.04.2012