legendary_rob
legendary_rob

Reputation: 13002

Set a session var in Rspec Request spec

I am trying to set a session variable in a request spec.

I have tried the following things to do this:

RSpec.describe 'Application Controller' do
  context 'updating an application' do
    before :each do
      @app = create(:application, step: 'investigation')
    end

    it 'should update app status' do
      Status.create(app_id: @app.id, name: Status.names[:start])
      request.session[:app_id] = @app.id
      patch "/applications/start",
            params: s_params
      expect(response).to redirect_to(offers_path)
    end
  end
end

I have tried substituting request with @request both result in the same output.

NoMethodError:
  undefined method `session' for nil:NilClass

then I have tried just setting as:

session[:app_id] = @app.id

which will yield:

NoMethodError:
  undefined method `session' for nil:NilClass

and also setting it like this:

patch "/applications/start",
      params: s_params,
      session: {"app_id" => @app.id}

which will yield:

 ArgumentError:
   unknown keyword: session

My versions:

╰>>> ruby -v
ruby 2.4.5p335 (2018-10-18 revision 65137) [x86_64-darwin18]

╰>>> rails -v
Rails 5.2.1

╰>>> rspec -v
RSpec 3.8
  - rspec-core 3.8.0
  - rspec-expectations 3.8.1
  - rspec-mocks 3.8.0
  - rspec-rails 3.8.0
  - rspec-support 3.8.0

Looking at the documentation it suggests we could leverage the sessions but does not give a clear example of how we would do this.

Upvotes: 23

Views: 10317

Answers (2)

channa ly
channa ly

Reputation: 9927

The most straightforward approach that comes into my mind is to mock the controller before doing the request:

 session = { app_id: @app.id }
 allow_any_instance_of(SomeController).to receive(:session).and_return(session)

 get some_resources_path
 expect(response).to ...

Upvotes: -1

s.stv
s.stv

Reputation: 352

First of all, little remark...

I recommend using 'type:' for RSpec test definition. It's good in anyways: easy to determinate by review and we will have the ability to define some extensions/customization for that type of tests(if needed).

The second point

We don't have request / response / controller methods(instance) before the request. Only after request, we will have them. By this reason we can't use request.session[:app_id] = @app.id before patch in your example...

The third point

@app it is a risky name of variable, not sure it will be a problem or not, but will be better to rename it

One of the possible solution

You can try to use some stubs for it, for example: allow_any_instance_of(ActionDispatch::Request).to receive(:session) { { app_id: '11' } }

Notes

The requests methods get / post / patch / and etc are differrent from similar controller test methods. All they are handling by process method. More details you can find here

Upvotes: 15

Related Questions