Разработка, Rspec, ожидания пользователей - PullRequest
2 голосов
/ 22 апреля 2011

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

it "should retrieve something for user" do
  @user = Factory.create(:user) 
  sign_in @user
  @user.expects(:something)
  get :manage
end

проблема, с которой я столкнулся, заключается в том, что ожидаемые результаты не будут выполнены, если я не сделаю:Пользователь - помощник по разработке.после копания в отладчике также появляется, когда не выдумывая current_user, @user действительно возвращается, так что я не уверен, почему ожидание не оправдалось.

1 Ответ

3 голосов
/ 22 апреля 2011

Текущий пользователь сериализуется перед сохранением в сеансе;скорее всего, для модели пользователя ActiveRecord хранится идентификатор пользователя:

https://github.com/plataformatec/devise/blob/master/lib/devise/test_helpers.rb#L49

Это означает, что когда ваш контроллер снова выбирает пользователя:

https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb#L47-49

это поиск user_id в сеансе и повторное извлечение пользователя из базы данных.

Это означает, что объект User, возвращенный #current_user в контроллере, является объектом Ruby, отличным от @Пользователь, которого вы передаете в #sign_in в своем тесте, так что заглушки и ожидания от одного объекта не привязаны к другому.

Я не очень широко использовал Devise / Warden, но уверен, что это происходит,Вы можете попробовать распечатать #object_id на двух экземплярах, чтобы подтвердить это.

Обновление семантики Picky Фев 2014:

Заглушка #current_user на вашем контроллере - это хороший подходздесь, в зависимости от вашего определения «границы» тестируемой системы (SUT) - т.е. ваш контроллер.Предполагая, что метод #current_user определен Devise и смешан с вашим контроллером Devise, вы можете утверждать, что #current_user является внешним по отношению к вашему SUT и, следовательно, является честной игрой для заглушки.

Вы можете альтернативно заглушить нижележащий слойчто Devise обращается к (ActiveRecord), скажем, вставив User.find, чтобы вернуть ваш @user объект.Это означает, что ваша спецификация тестирует как вашу реализацию действий, так и реализацию Devise #current_user, поэтому спецификация потерпит неудачу, если одна из этих вещей будет изменена позже.

Допустим, Devise использует User.find(args), и скажем,вы заглушаете этот метод, и затем более поздняя версия Devise изменилась на использование User.where(args).first() - ваш код не изменился, но базовая библиотека изменилась, и ваша спецификация не работает.Если в общих чертах подумать об этой идее, то бывают ситуации, когда вам, вероятно, понравится такое поведение (подумайте о том, чтобы смоделировать необработанный HTTP-ответ, например, с помощью WebMock вместо использования заглушек Net::HTTP, чтобы впоследствии вы могли поменять местами http-библиотеки), и раз вы не будете (возможно, этот вопрос Devise считается за один).

...