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

21

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

我尝试了以下方法来实现这个目标:

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

我已经尝试用@request替换request,两者都得到了相同的输出。

NoMethodError:
  undefined method `session' for nil:NilClass

那么我尝试仅将其设置为:

session[:app_id] = @app.id

这将产生以下结果:

NoMethodError:
  undefined method `session' for nil:NilClass

并且可以像这样进行设置:

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

这将产生:

 ArgumentError:
   unknown keyword: session

我的版本:

╰>>> 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

看文档建议我们可以利用会话,但没有清楚的示例说明如何做到这一点。


你有查看过 https://dev59.com/c2Eh5IYBdhLWcg3wZyzG 吗? - ldeld
是的,我尝试了那篇帖子中提到的每个建议。在我的测试中,我没有从ActionController::TestCaseActionDispatch::IntegrationTest继承。看起来,在调用对象之后,您只能访问请求,但在进行调用之前,我需要设置会话。 - legendary_rob
好的,抱歉。在文档中没有找到直接使用会话的任何内容,但也许这可以帮助您:似乎您可以使用 cookies['key'] :https://github.com/rspec/rspec-rails/blob/master/features/controller_specs/Cookies.md - ldeld
可能是 RSpec set session object 的重复问题。 - Paweł Gościcki
2个回答

11

首先,小备注一下...

我建议在RSpec测试定义中使用"type:"。它有很多好处:易于通过审查确定,并且如果需要,我们将有能力为该类型的测试定义一些扩展/定制。

第二点

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

第三点

@app是一个具有风险的变量名称,不确定它是否会成为问题,但最好重命名

可能的解决方案之一

你可以尝试使用一些存根(stubs)来解决这个问题,例如:allow_any_instance_of(ActionDispatch::Request).to receive(:session) { { app_id: '11' } }

备注

get/post/patch等请求方法与类似的控制器测试方法不同。它们都由process方法处理。更多详情请参见这里


-2
我想到的最直接的方法是在发出请求之前模拟控制器:
 session = { app_id: @app.id }
 allow_any_instance_of(SomeController).to receive(:session).and_return(session)

 get some_resources_path
 expect(response).to ...

这在 Rails 7.0.4.3 中似乎无法工作。 - olleicua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接