【问题标题】:nil response object in Rails 5.2, RSpec-Rails 3.7 spec for GET requestRails 5.2 中的 nil 响应对象,用于 GET 请求的 RSpec-Rails 3.7 规范
【发布时间】:2018-07-04 23:44:17
【问题描述】:

我一直对此深有感触,觉得我可能犯了一个简单的错误,但我无法找到有关此问题的任何信息。

我有一些 Rails 5 的请求规范,当我测试重定向时——但不是渲染模板——我得到一个错误,undefined method 'response_code' for nil:NilClass。原因似乎是 @response 在调用匹配器时是 nil(在 ActionDispatch::Assertions::ResponseAssertions 代码中,而不是在我的代码中)。我可以使用 cURL 向 API 发出请求,它会按预期返回响应。返回错误的点在这里(这是ActionDispatch代码):

def generate_response_message(expected, actual = @response.response_code)
  "Expected response to be a <#{code_with_name(expected)}>,"\
  " but was a <#{code_with_name(actual)}>"
  .dup.concat(location_if_redirected).concat(response_body_if_short)
end

注意第一行,actual 参数的默认值设置为@response.response_code

这是我的测试代码:

RSpec.describe "Admin registrations", type: :request do
  describe "new sign-up" do
    subject { get new_admin_registration_path }

    it "redirects to home" do
       expect(subject).to redirect_to(new_admin_session_path)
    end
  end
end

测试日志中的相关行是:

Started GET "/admins/sign_up" for 127.0.0.1 at 2018-07-05 10:44:05 -0700
Processing by Admins::RegistrationsController#new as HTML
Redirected to http://example.org/admins/sign_in
Completed 301 Moved Permanently in 18ms (ActiveRecord: 0.0ms)

有趣的是,当我使用 byebug 检查subject 的值时,它确实返回了一个 Rack::MockResponse 对象,所以这在某种程度上没有通过。

非常感谢我能得到的任何帮助!

【问题讨论】:

  • 嗯,规范看起来不错。有什么要分享的日志吗?另外,如果你改用get 'somepath/someresource' 会发生什么
  • get "somepath/someresource" 给我一个路由错误。我在日志中没有看到任何异常,但我会在问题中添加内容。
  • 对不起,我的意思是不要像你正在做的那样使用路径助手,不管new_admin_registration_path 的字符串是什么。
  • 哦!我试过了,结果一样。

标签: ruby-on-rails rspec rack-test


【解决方案1】:

我确定您可能已经解决了这个问题,但是对于任何可能偶然发现这个问题的人,我们遇到了同样的事情(response 在提出请求后没有被分配 - get 或 @ 987654323@,没有尝试其他方法,但假设它们都相同)。一直有效的现有请求规范都开始失败。

在我们的案例中,罪魁祸首被追查到rails_helper.rb 中所需的模块,并添加到 rspec 的 config.include 列表中:

config.include ApiHelper, type: request

AppHelper 内部是根本原因:

include Rack::Test::Methods

注释掉那一行(最终对我们来说,删除整个帮助器,因为它并不是真正需要的)将请求规范恢复到它们之前的工作状态。

tl;博士:

确保您不会无意中将 Rack::Test::Methods 包含在您的 rspec 配置中的 config.include 中。

【讨论】:

  • 感谢您分享这个!从某种意义上说,我确实解决了这个问题,但它是通过猴子修补一些东西,所以这是一个更令人满意的解决方案。
  • 这也是我的问题。我将 Rack::Test::Methods 添加到规范中以测试上传 CSV,但随后我花了半个小时摸索一切工作的方式,但 response 对象为零。
【解决方案2】:

这对我来说很愚蠢,但我敢打赌别人或我自己会不小心这样做。

如果 type: :request 已在您的顶部块中设置,还请确保您不会意外覆盖块中的 response 变量。

以我愚蠢的自我为例作为警告:

let(:response) { }

it 'overrides rspec\'s own dediciated response variable' do
   get your_route_here_path
   expect(response).to have_http_status(:ok)
end

结果如下:

Error: nil doesn't have property 'status'

这是因为 let(:response) 实际上覆盖了 rspec 自己的内部 response

请记住,您可能永远不会像这样搞砸,但以防万一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多