Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails, how to test 400 response with missing parameter

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).

like image 906
tompave Avatar asked Dec 09 '15 18:12

tompave


1 Answers

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
like image 148
dferrazm Avatar answered Oct 14 '22 04:10

dferrazm