Rails, как проверить ответ 400 с отсутствующим параметром

Я работаю с Rails 4.2.5 и пытаюсь проверить ожидаемый ответ 400 от контроллера в случае некорректного запроса. Логика проверки параметров обрабатывается strong_parameters.

контекст

В моем контроллере у меня есть:

def user_params
  params.require(:user).permit(:foo, :bar, :baz)
end

И я ссылаюсь на user_params в запросе POST с заголовками Accept и ContentType, установленными на application/json.

В development отправка POST без параметра user вызовет исключение ActionController::ParameterMissing.
Если я установлю это в своем файле environments/development.rb:

Rails.application.configure do
  config.consider_all_requests_local = false
end

Rails будет действовать как в production и вернет простой ответ 400 вместо страницы отладки. Здорово.

эта проблема

Однако у меня возникают проблемы с выполнением того же самого в тестах контроллера (rspec-rails ~> 3.4).

В частности, это пройдет:

expect {
  post :action, malformed_params
}.to raise_error(ActionController::ParameterMissing)

но этого не произойдет из-за поднятого исключения:

post :action, malformed_params
expect(response.status).to eql 400

Я уже пытался перевернуть consider_all_requests_local для тестовой среды, безрезультатно.

Любое решение? На это есть старый ответ, но это не помогает (и даже аскер признал, что это бесполезно).

Редактировать:

Как было сказано в комментариях, вот параметры из спецификации контроллера:

let(:user_data) do
  { foo: "foo", bar: "bar", baz: "baz" }
end

let(:good_params) do
  {
    some_id: SecureRandom.uuid,
    user: user_data
  }
end

let(:malformed_params) do
  { some_id: SecureRandom.uuid }.merge(user_data)
end

let(:incomplete_params) do
  { some_id: SecureRandom.uuid }
end

good_params подходит для счастливого пути. Ни malformed_params, ни incomplete_params не работают, когда я хочу протестировать 400: оба вызовут исключение и вызовут сбой теста.

Я уже убедился, что те же полезные данные параметров будут работать при отправке POST на работающий сервер (в development, но с измененной конфигурацией, как описано выше).


person tompave    schedule 09.12.2015    source источник
comment
Как устроен malformed_parmas? Не могли бы вы поделиться им, пожалуйста?   -  person NickGnd    schedule 09.12.2015
comment
medium.com /@эдгар/   -  person ConorB    schedule 10.06.2020


Ответы (3)


Если вы хотите имитировать производство во всех средах и всегда поднимать 400, когда какой-либо требуемый параметр отсутствует, вместо изменения каждого файла конфигурации вы можете просто добавить свой контроллер (или ApplicationController или любой другой миксин, чтобы сделать его более общим):

# assuming we're talking about a JSON API

rescue_from ActionController::ParameterMissing do |e|
  render json: { error: e.message }, status: :bad_request
end

# or more general for any kind of response

rescue_from ActionController::ParameterMissing do |e|
  head :bad_request
end
person dferrazm    schedule 27.12.2018

Проблема в том, что вы пытаетесь получить хэш с ключом :user в вашем контроллере. Поскольку этот хеш недоступен для неправильных тестов, он вызовет исключение.

Попробуйте что-то вроде этого:

post :action, user: malformed_params

Я не проверял это, но это должно работать.

Удачного кодирования. :)

person Tobias    schedule 09.12.2015
comment
Нет, я хочу проверить, отвечает ли контроллер 400, если параметр отсутствует. Я не хочу проверять успешный ответ. Я намеренно отправляю некорректный запрос. - person tompave; 09.12.2015

Возникшее исключение является правильным, поскольку не отправляет искаженный json. Полезная нагрузка хорошо отформатирована, но отсутствует params.

Вы должны попробовать что-то подобное в:

'{ i am malformed json'
person NickGnd    schedule 09.12.2015
comment
Нет, я не пытаюсь проверить синтаксическую структуру JSON. Я пытаюсь проверить ответ, если параметр отсутствует, и ответ должен быть 400, а не исключение. - person tompave; 09.12.2015