在Rspec请求规范中设置会话变量

The*_*end 8 session rspec ruby-on-rails

我正在尝试在请求规范中设置会话变量。

我尝试了以下操作来做到这一点:

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
Run Code Online (Sandbox Code Playgroud)

我尝试request@request两个结果替换为相同的输出。

NoMethodError:
  undefined method `session' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)

然后我尝试只设置为:

session[:app_id] = @app.id
Run Code Online (Sandbox Code Playgroud)

这将产生:

NoMethodError:
  undefined method `session' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)

并设置如下:

patch "/applications/start",
      params: s_params,
      session: {"app_id" => @app.id}
Run Code Online (Sandbox Code Playgroud)

这将产生:

 ArgumentError:
   unknown keyword: session
Run Code Online (Sandbox Code Playgroud)

我的版本:

?>>> 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
Run Code Online (Sandbox Code Playgroud)

在查看文档时,它表明我们可以利用这些会话,但是没有给出如何执行此操作的清晰示例。

小智 5

首先,少说...

我建议使用 'type:' 作为 RSpec 测试定义。无论如何它都很好:通过审查很容易确定,我们将能够为该类型的测试定义一些扩展/自定义(如果需要)。

第二点

我们没有request/ response/controller请求之前的方法(实例)。只有在要求后,我们才会得到它们。由于这个原因,我们不能在您的示例中使用request.session[:app_id] = @app.id之前patch...

第三点

@app 这是一个危险的变量名称,不确定它是否有问题,但重命名它会更好

可能的解决方案之一

您可以尝试使用一些存根,例如: allow_any_instance_of(ActionDispatch::Request).to receive(:session) { { app_id: '11' } }

笔记

请求方法 get / post / patch / 等不同于类似的控制器测试方法。他们都是按process方法处理的。您可以在此处找到更多详细信息