2014-03-17 3 views
23

Я пытаюсь установить объект сеанса из спецификации моего контроллера.RSEE set session object

it 'use invalid coupon' do 
    session[:coupon] = 'abcd'  
    Service.any_instance.stub(:validate_coupon).with(session[:coupon]).and_return('abcd') 

    get :index 
    expect(flash[:coupon__notice]).to be nil 
end 

, но когда я проверить сессии, вместо объекта @coupon, я получаю @data, который содержит строку «купон», и тест не пройден.

+0

Что делает 'validate_coupon'? Разве вы не хотели делать - 'Service.any_instance.stub (: validate_coupon) .with (: coupon) .and_return ('abcd')'? Как бы то ни было, это фактически 'Service.any_instance.stub (: validate_coupon) .with ('abcd'). And_return ('abcd')', так как 'session [: coupon]' is ''abcd'' ... –

ответ

43

Это объясняется в Guide to Testing Rails Applications в разделе 4 «Функциональных тестов для контроллеров get действия принимает Params хэш и сеанса хеш-функцию, например:.

get(:show, {'id' => "12"}, {'user_id' => 5}) 

Вы должны быть в состоянии пройти в nil для Params хэш в вашем примере, а затем передать в желаемые параметры сеанса:

get :index, nil, {coupon: 'abcd'} 

Я рекомендую тщательное чтение Rails руководство для тех, кто с помощью RSpec для Тестирование Rails. rspec-rails использует существующие тестовые классы Rails, что не совсем ясно в документах rspec-rails.

+0

Вы совершенно правы! Я пропустил некоторые части из Rails Guide. Знаете ли вы разницу между предложенным методом и присваиваете явно определенное значение сеансу, например session [: coupon] = 'abcd'. Просто потому, что иногда, похоже, тоже работает. – parov

12

Вы также можете использовать @request объект как

@request.session['coupon'] = 'abcd' 
+0

спасибо большое, это за меня. – Haider

+0

рад, что это было полезно! @Haider –

+0

Не до того, как запрос был сделан –

23

В Rails 5+, если вы используете ActionController::TestCase сессии передается в качестве ключевого слова арг.

Установка Титулы и сессия будет выглядеть следующим образом:

get(:show, params: {'id' => "12"}, session: {'user_id' => 5}) 

Установка только сеанс будет выглядеть,

get(:show, session: {'user_id' => 5}) 

Если вы используете ActionDispatch::IntegrationTest, который является новым значением по умолчанию для для тестирования контроллера, вы можете указать , а не, чтобы установить переменные сеанса и установить их, пройдя свой тест через поток входа.

+0

Спасибо за отзыв @HParker;) – Avir94

+4

Похоже, что это работает только в ActionController :: TestCase, который больше не является родительским классом по умолчанию для спецификаций контроллера. По умолчанию используется ActionDispatch :: IntegrationTest, который не предоставляет метод установки переменных сеанса, а [DHH рекомендует делать фактический запрос для имитации входа в систему с интерфейсом] (https://github.com/rails/rails/issues/23386 # issuecomment-178013357), (как и соглашение об интеграционном тесте). – mltsy

+1

Спасибо @mltsy! Я обновил ответ, чтобы включить информацию о том, когда ваш базовый класс «ActionDispatch :: IntegrationTest». Дайте мне знать, если я ошибаюсь. – HParker