Как установить заголовки запроса в спецификации запроса rspec?

127

В спецификации контроллера я могу установить заголовок принятия http следующим образом:

request.accept = "application/json"

но в спецификации запроса объект «запрос» равен нулю. Так как я могу это сделать здесь?

Причина, по которой я хочу установить заголовок http accept в json, заключается в том, что я могу сделать это:

get '/my/path'

вместо этого

get '/my/path.json'
Сергей
источник

Ответы:

130

Вы должны иметь возможность указать HTTP-заголовки в качестве третьего аргумента вашего метода get (), как описано здесь:

http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html#method-i-get

и тут

http://api.rubyonrails.org/classes/ActionDispatch/Integration/Session.html#method-i-process

Итак, вы можете попробовать что-то вроде этого:

get '/my/path', nil, {'HTTP_ACCEPT' => "application/json"}
awaage
источник
3
Нам нужно было использовать HTTP_ACCEPT: get '/my/path', nil, {'HTTP_ACCEPT' => "application/json"}
Мэтт Скилипоти,
58
ПРИМЕЧАНИЕ. Это для интеграционного тестирования, аналогично комментарию ниже, в тестах контроллера rspec-rails вы должны использовать: request.env ["HTTP_ACCEPT"] =
Alex Soto
5
Небольшая ошибка, с которой я столкнулся из-за своей глупости: ключи заголовка должны быть строками. Символы не появятся.
аймурманн
@ajmurmann Теперь символы работают: заголовок "Авторизация" можно :authorization .
Франклин Ю,
13
Новый синтаксис RSspec 3 будет иметь вид get my_resource_path, params: {}, headers: { 'HTTP_ACCEPT' => "application/json" }`
Сирил Дюшон-Дорис
39

Я использовал это в Test :: Unit:

@request.env['HTTP_ACCEPT'] = "*/*, application/youtube-client"
get :index
Сыце Сиджбрандий
источник
3
Точно так же, как отмечает Алекс Сото в комментарии к другому ответу, в тестах контроллеров rspec-rails вы можете использовать: request.env ["HTTP_ACCEPT"]
gerry3
ActionController::TestCase
Большое
+1 Я пробовал использовать ключ, указанный Cookieв хэше заголовков (потому что это то, что отправляет мой браузер), но это не сработало. Потом я сделал request.keysи увидел ключ с названием HTTP_COOKIE. Использование этого сработало. Они действительно должны лучше документировать это.
Кельвин
Это действительно работает! Я также нашел этот ответ в github.com/rspec/rspec-rails/issues/65
Степан Захаров,
@Sytse Sijbrandij Никто не спрашивал о Test :: Unit. Вопрос задан по поводу rspec.
Брайан Димас
19

Это работает для спецификаций контроллера, а не для спецификаций запроса:

request.headers["My Header"] = "something"
Моргот
источник
2
Это сработало для меня, это зависит от того, как вы извлекаете заголовки, используете ли вы request.headersилиrequest.env
Эдгар Ортега
3
Примечание: это для тестов контроллера, а не для интеграционных тестов, упомянутых в вопросе.
Франклин Ю
3
не работал для интеграционных тестов. Однако работает с тестами контроллера.
Петр Газаров
18

Я добавляю это здесь, так как я сильно застрял, пытаясь сделать это в Rails 5.1.rc1

Сигнатура метода get теперь немного изменилась.

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

get /some/path, headers: {'ACCEPT' => 'application/json'}

К вашему сведению, полный набор аргументов ключевых слов:

params: {}, headers: {}, env: {}, xhr: false, as: :symbol

Жюль Коупленд
источник
9

Мне нужно настроить заголовки отдельно

request.headers["Accept"] = "application/json"

Попытка отправить его через get / delete / .... - это полный мусор в rails4 и вызывает боль в моей голове, потому что он никогда не отправляется как заголовок, а как параметр.

{"Accept" => "application/json"}
user4694178
источник
5
Действительно ли это дает ответ на вопрос OP? Если это новый вопрос, лучше задать новый вопрос.
β.εηοιτ.βε
9

Использование rspec с Rack::Test::Methods

header 'X_YOUR_HEADER_VAR', 'val'
get '/path'

Заголовок var будет выглядеть как X-Your-Header-Var

marcusb
источник
Примечание: это Test::Unitдля RSpec, а не для него.
Франклин Ю
его указывающий rspec
Джеймс Тан
1
Да. В rspec это вызывает ndefined method 'header'у меня ошибку.
Евгений Масленков
7

С RSpec 3 вы можете использовать следующий синтаксис

get my_resource_path, params: {}, headers: { 'HTTP_ACCEPT' => "application/json" }

Как описано в официальной документации Rspec (ссылка указывает на v3.7)

Сирил Дюшон-Дорис
источник
Сладкий. Именно то, что я искал. Спасибо!
Франсиско Кинтеро,
5

Чтобы отправить оба xhr: trueзаголовка и заголовки, мне пришлось сделать, например:

my_headers = { "HTTP_ACCEPT": "application/json" }
get my_path, xhr: true, headers: my_headers
Джим Стюарт
источник
1
Вот исходный код на GitHub: github.com/rails/rails/blob/…
Карл Уилбур
Не должно headers =быть my_headers =?
webaholik
Исправлена. Спасибо @webaholik.
Джим Стюарт
2

На ваш вопрос уже был дан ответ, но если вы хотите отправить что-то в другое действие, вы должны сделать это:

post :save, {format: :json, application: {param1: "test", param2: "test"}}
Игорь Эскобар
источник
2

Попробуйте что-нибудь вроде:

get :index, :format => 'json' 
gayavat
источник
Не уверен, но, вероятно, работает, потому что rails ищет .format для этого маршрута; это сработало и для меня.
Алан
2
Если кому-то интересно, это просто добавляется format=jsonкак параметр запроса. Не то же самое, что и поле заголовка.
Кевин Кармоди,