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
.
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.
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).
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).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With