2

I'd like to test with RSpec a controller receiving this kind of request:

curl -X POST                                   \
  --data   "{\"same_key\": \"value_in_body\"}" \
  --header "same_key: value_in_header"         \
  "http://localhost:5000/articles/?same_key=value_in_querystring"

having:

  • same_key in the body
  • same_key in the header
  • same_key in the querystring

and where:

  • request.request_parameters["same_key"]: "value_in_body"
  • request.headers["same_key"]: "value_in_header"
  • request.query_parameters["same_key"]: "value_in_querystring"

I wrote this test:

RSpec.describe ArticlesController, type: :controller do
  describe '#create' do
    it 'creates an article' do
      post :post,
        as:      :json,
        params:  { same_key: 'value_in_body' },
        headers: { same_key: 'value_in_header' }

      expect(response).to have_http_status(:created)
    end
  end
end

So far, it would be good for the body param and the header param.

But how should we do to also send the querystring param?

2 Answers2

1

If you really need this kind of scenario, you have to use the Rails URI pattern instead of only specifying action name in the post statement,

post '/documents/create_new_doc', params: {same_key: 'value_in_body'}

Note: Get the exact URI pattern from rake routes

Mohanraj
  • 4,056
  • 2
  • 22
  • 24
  • I know this. But then how can we do to not override the _body_ param (because both have the same key)? – Cirus Polis Sep 01 '17 at 13:48
  • Yeah, I got your point, because it's a post request. So, instead of using action name you can use the RUI pattern like 'sessions/' that you can get it from rake routes. – Mohanraj Sep 01 '17 at 17:52
  • This pattern is used by RSpec's request tests. In the context of a RSpec's controller test, the first argument must be an action, not a path. – Cirus Polis Sep 01 '17 at 20:47
  • @CirusPolis: Have you tried by Rails URI pattern? Actually Rails RSpec should allow url patten as well. – Mohanraj Sep 02 '17 at 05:16
  • Yes. Unfortumally, it is working for request spec (https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec), but not for controller specs (https://relishapp.com/rspec/rspec-rails/docs/controller-specs). – Cirus Polis Sep 02 '17 at 14:03
0

You actually can't have both request.query_parameters and request.request_parameters at the same time from either post or get functions in RSpec Controller tests or Request tests. This other Stack Overflow answer explains that RSpec only ever sets one or the other: https://stackoverflow.com/a/36715875/2479282

The solution (posed by that other answer) is to use IntegrationTests instead, a'la:

class CollectionsTest < ActionDispatch::IntegrationTest
  test 'foo' do
    post collections_path, { collection: { name: 'New Collection' } }, 
                           { "QUERY_STRING" => "api_key=my_api_key" }

    # this proves that the parameters are recognized separately in the controller
    # (you can test this in you controller as well as here in the test):
    puts request.POST.inspect
    # => {"collection"=>{"name"=>"New Collection"}}
    puts request.GET.inspect
    # => {"api_key"=>"my_api_key"}
  end
end
Sean
  • 2,315
  • 20
  • 25