Rails 5 Integration test fails with NoMethodError: undefined method `[]=' for nil:NilClass when using Devise helper sign_in
Rails 5 Integration test fails with NoMethodError: undefined method `[]=' for nil:NilClass when using Devise helper sign_in
我正在使用内置的 Minitest 为 Rails v5.1 编写集成测试。
这是集成测试 class:
require 'test_helper'
class PuppiesEndpointsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "DELETE puppy" do
marty = people(:marty)
sign_in(marty)
# delete puppies_delete_path(marty.puppies.first.id)
# delete `/api/v1/puppies/destroy/${marty.puppies.first.id}.json`
# delete puppies_path(marty.puppies.first.id)
delete '/api/v1/puppies/destroy/6666.json'
assert_response :success
end
end
以上所有路由,包括被注释掉的路由,都会导致相同的神秘错误:
Error:
PuppiesEndpointsTest#test_DELETE_puppy:
NoMethodError: undefined method `[]=' for nil:NilClass
test/integration/puppies_endpoints_test.rb:17:in `block in <class:PuppiesEndpointsTest>'
bin/rails test test/integration/puppies_endpoints_test.rb:7
它不提供堆栈跟踪或任何其他信息来诊断它到底在说什么。我使用 byebug 在抛出错误的 delete
行之前调试 marty
变量。它显示了关联(夹具)记录的预期小狗数组。
我还在控制器操作的最顶部放置了一个 byebug,这个错误在到达那个 byebug 之前没有通过测试,所以我认为这几乎排除了操作代码中的任何内容。
这是我在 运行 rake routes
:
时看到的相关内容
PATCH /api/v1/puppies/edit/:id(.:format) puppies#update
DELETE /api/v1/puppies/destroy/:id(.:format) puppies#destroy
puppies_create POST /api/v1/puppies/create(.:format) puppies#create
这是我的路线文件中的实际内容:
scope '/api' do
scope '/v1' do
devise_for :people
patch 'puppies/edit/:id' => 'puppies#update'
delete 'puppies/destroy/:id' => 'puppies#destroy'#, as: 'puppies_delete'
post 'puppies/create' => 'puppies#create'
...
我完全被难住了 what/why 我收到了这个错误。实际代码完全按预期工作。
我的直觉是,可能缺少一个没有为测试环境设置的配置变量(我使用 dotenv gem),但我不知道如果错误不会发生,如何追踪它给我任何上下文。
更新
我已将此问题与使用 Devise 助手 sign_in
方法隔离开来。当我删除此方法调用时,问题就消失了。
这是有问题的测试 class:
require 'test_helper'
class PuppiesEndpointsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "do stuff" do
...
app/controllers/api_controller.rb:
class ApiController < ActionController::API
end
可能 sign_in
不适用于测试未继承自 ActionController::Base
的控制器
我将控制器更改为从 ActionController::Base
继承,但没有任何变化。我仍然无法在不出现该错误的情况下使用 sign_in
,但是如果我 "manually" post
对 sign_in 端点的请求,它会起作用。
更新 2
我发现这个设计问题听起来与我的问题有关:https://github.com/plataformatec/devise/issues/2065
看来我找到了 issue。显然,在 rails-api 模式下, ActionDispatch::Cookies 和 ActionDispatch::Session::CookieStore 中间件被插入到中间件堆栈的末尾,这在正常 Rails模式。
因此,这些中间件包含在 Warden::Manager 之后,这在请求规范中造成了一些混乱。
尝试在test.rb
中设置
Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies
Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Session::CookieStore
我正在使用内置的 Minitest 为 Rails v5.1 编写集成测试。
这是集成测试 class:
require 'test_helper'
class PuppiesEndpointsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "DELETE puppy" do
marty = people(:marty)
sign_in(marty)
# delete puppies_delete_path(marty.puppies.first.id)
# delete `/api/v1/puppies/destroy/${marty.puppies.first.id}.json`
# delete puppies_path(marty.puppies.first.id)
delete '/api/v1/puppies/destroy/6666.json'
assert_response :success
end
end
以上所有路由,包括被注释掉的路由,都会导致相同的神秘错误:
Error:
PuppiesEndpointsTest#test_DELETE_puppy:
NoMethodError: undefined method `[]=' for nil:NilClass
test/integration/puppies_endpoints_test.rb:17:in `block in <class:PuppiesEndpointsTest>'
bin/rails test test/integration/puppies_endpoints_test.rb:7
它不提供堆栈跟踪或任何其他信息来诊断它到底在说什么。我使用 byebug 在抛出错误的 delete
行之前调试 marty
变量。它显示了关联(夹具)记录的预期小狗数组。
我还在控制器操作的最顶部放置了一个 byebug,这个错误在到达那个 byebug 之前没有通过测试,所以我认为这几乎排除了操作代码中的任何内容。
这是我在 运行 rake routes
:
PATCH /api/v1/puppies/edit/:id(.:format) puppies#update
DELETE /api/v1/puppies/destroy/:id(.:format) puppies#destroy
puppies_create POST /api/v1/puppies/create(.:format) puppies#create
这是我的路线文件中的实际内容:
scope '/api' do
scope '/v1' do
devise_for :people
patch 'puppies/edit/:id' => 'puppies#update'
delete 'puppies/destroy/:id' => 'puppies#destroy'#, as: 'puppies_delete'
post 'puppies/create' => 'puppies#create'
...
我完全被难住了 what/why 我收到了这个错误。实际代码完全按预期工作。
我的直觉是,可能缺少一个没有为测试环境设置的配置变量(我使用 dotenv gem),但我不知道如果错误不会发生,如何追踪它给我任何上下文。
更新
我已将此问题与使用 Devise 助手 sign_in
方法隔离开来。当我删除此方法调用时,问题就消失了。
这是有问题的测试 class:
require 'test_helper'
class PuppiesEndpointsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "do stuff" do
...
app/controllers/api_controller.rb:
class ApiController < ActionController::API
end
可能 sign_in
不适用于测试未继承自 ActionController::Base
我将控制器更改为从 ActionController::Base
继承,但没有任何变化。我仍然无法在不出现该错误的情况下使用 sign_in
,但是如果我 "manually" post
对 sign_in 端点的请求,它会起作用。
更新 2 我发现这个设计问题听起来与我的问题有关:https://github.com/plataformatec/devise/issues/2065
看来我找到了 issue。显然,在 rails-api 模式下, ActionDispatch::Cookies 和 ActionDispatch::Session::CookieStore 中间件被插入到中间件堆栈的末尾,这在正常 Rails模式。
因此,这些中间件包含在 Warden::Manager 之后,这在请求规范中造成了一些混乱。
尝试在test.rb
中设置Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies
Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Session::CookieStore