Текущий пользователь сериализуется перед сохранением в сеансе;скорее всего, для модели пользователя 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 считается за один).