我正在使用内置的Minitest为Rails v5.1编写集成测试。
这是集成测试类:
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来调试marty
变量,正好在引发错误的delete
行之前。它显示了相关(夹具)记录的预期幼犬数组。
我还在控制器动作的顶部放置了一个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'
...
我完全不知道为什么/为什么我得到这个错误。实际代码完全按预期工作。
我的预感是,可能有一个缺少的配置变量没有为测试环境设置(我使用dotenv gem),但我不知道如果错误不会给我任何上下文,如何跟踪它。
UPDATE
我已经将此问题与使用Devise帮助器sign_in
方法隔离开来。当我删除此方法调用时,问题就消失了。
这是有问题的测试类:
require 'test_helper'
class PuppiesEndpointsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "do stuff" do
...
应用程序/控制器/ api_controller.rb:
class ApiController < ActionController::API
end
也许sign_in
不能用于测试不从ActionController :: Base继承的控制器
我改变了控制器继承ActionController::Base
并没有改变。我仍然无法使用sign_in
而不会出现该错误,但是如果我“手动”post
向sign_in端点发出请求,它就可以找到。
更新2我发现这个设备问题听起来与我的问题有关:qazxsw poi
看起来我找到了https://github.com/plataformatec/devise/issues/2065。显然,在rails-api模式下,ActionDispatch :: Cookies和ActionDispatch :: Session :: CookieStore中间件被插入到中间件堆栈的末尾,这在正常的Rails模式下不会发生。
因此,这些中间件包含在Warden :: Manager之后,它会在请求规范中混淆一些东西。
尝试在test.rb中设置
issue