Rails 5.2中的nil响应对象,针对GET请求的RSpec-Rails 3.7规范

7

我一直在专注于这个问题,但感觉可能是犯了一个简单的错误,不过我没有找到任何关于这个问题的信息。

我有几个针对Rails 5的请求规范,在测试重定向时(但不测试渲染的模板),我遇到一个错误:undefined method 'response_code' for nil:NilClass。原因似乎是当匹配器被调用时(在ActionDispatch::Assertions::ResponseAssertions代码内部而非我的代码中),@responsenil。我可以使用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' 会发生什么? - Anthony
执行 get "somepath/someresource" 时出现路由错误。日志中没有异常信息,但我会将所有相关信息添加到问题描述中。 - Dana Scheider
抱歉,我的意思是不要像你现在这样使用路径助手,而是使用字符串等效的 new_admin_registration_path - Anthony
哦!我试过了,结果一样。 - Dana Scheider
2个回答

4
我相信您可能已经解决了这个问题,但是对于其他可能会遇到这个问题的人来说,我们也遇到了同样的问题(在请求(无论是get还是post)之后没有分配response,没有尝试其他方法,但是认为它们都是一样的)。现有的请求规范开始失效。
在我们的情况下,罪魁祸首被追踪到一个模块,该模块在rails_helper.rb中被要求,并添加到rspec的config.include列表中。
config.include ApiHelper, type: request

AppHelper是问题的根本原因:

include Rack::Test::Methods

将该行注释掉(对我们来说,最终删除整个帮助程序,因为它实际上并不需要),将请求规范恢复到之前的工作状态。

简而言之:

确保不要无意中在rspec配置中包含Rack::Test::Methods。


谢谢你分享这个!我确实解决了这个问题,但是通过猴子补丁的方式,所以这个方法更加令人满意。 - Dana Scheider
这也正是我的问题。我在一个spec中添加了Rack::Test::Methods以测试上传CSV文件,但接下来的半个小时里我一直在想为什么所有东西都能正常工作,但response对象为空。 - clockworkpc

2

我很蠢,但我敢打赌其他人或我自己也会不小心这样做。

如果你的顶部块已经设置了: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

结果会像这样:

错误:nil没有属性'status'

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

只是要记住,你可能永远不会像这样搞砸,但以防万一。


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