Rails, how to test 400 response with missing parameter
Asked Answered
S

2

9

I'm working with Rails 4.2.5, and I'm trying to test an expected 400 response from a controller in case of malformed request. The parameter validation logic is handled by strong_parameters.

the context

In my controller I have:

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

And I'm referencing user_params in a POST request with Accept and ContentType headers set to application/json.

In development, POSTing without a user parameter will raise a ActionController::ParameterMissing exception.
If I set this in my environments/development.rb file:

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

Rails will act like in production and return a simple 400 response instead of the debug page. Great.

the problem

I'm having troubles doing the same thing in my controller tests, though (rspec-rails ~> 3.4).

Specifically, this will pass:

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

but this won't because of the raised exception:

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

I have already tried to flip the consider_all_requests_local for the test environment, to no avail.

Any solution? There is an old answer on this, but it does not help (and even the asker recognized it was not useful).

Edit:

As asked in the comments, here are the parameters from the controller spec:

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 works for the happy path. Neither malformed_params nor incomplete_params work when I want to test the 400: both will raise the exception and cause the test to fail.

I've already verified that the same parameter payloads will work when POSTing to a running server (in development, but with the configuration tweaked as described above).

Subservient answered 9/12, 2015 at 18:48 Comment(2)
How is malformed_parmas ? Could you share it please?Pennyroyal
medium.com/@edgar/…Cataclinal
B
4

If you want to simulate production across all environments and always raise 400 when any required parameter is missing, instead of changing each config file, you could just put in your controller (or ApplicationController or any other mixin to make it more general):

# 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
Belen answered 27/12, 2018 at 12:22 Comment(0)
P
-1

The exception raised is correct because are not sending a malformed json. The payload is formatted well, but is missing a params.

You have to try with something similar at :

'{ i am malformed json'
Pennyroyal answered 9/12, 2015 at 19:5 Comment(1)
No, I'm not trying to validate the JSON syntactical structure. I'm trying to check the response if a parameter is missing, and the response should be 400, not an exception.Subservient

© 2022 - 2024 — McMap. All rights reserved.