Rails测试:仅在GET请求中传递CSRF令牌

5

我正在尝试对我的控制器进行单元测试,使用 get 请求的每个测试都可以正常工作,但是在我使用其他调用(delete 在 destroy 中,post 在 create 中以及 put 在 update 中)的测试中会失败,并出现以下错误:

WARNING: Can't verify CSRF token authenticity
Completed 401 Unauthorized in 2.5ms

例如这是“destroy”功能的测试:
  test "should destroy blog" do
    assert_difference('Blog.count', -1) do
      delete :destroy, id: @blog
    end

    assert_redirected_to blogs_path
  end

无法工作

这是用于展示的测试,它可以正常工作:

  test "should show blog" do
    get :show, id: @blog
    assert_response :success
  end

在销毁(destroy)测试中,设备(devise)的authenticate_user!仅将我重定向到sign_in页面,测试失败。
2个回答

8
显然,在测试环境中禁用CSRF令牌是一件很普遍的事情, 我添加了:
  # Disable request forgery protection in test environment
  config.action_controller.allow_forgery_protection    = false

我添加了代码到我的 "/config/environments/test.rb" 文件中,当前用户已成功通过。


根据我的经验,你可能还需要将此设置添加到你的 test_helper.rb 中。请参见 https://stackoverflow.com/q/60940695/1196465 - David Gay
如果您不想在控制器单元测试中禁用CSRF,该怎么办?您必须使用Devise吗? - nimmolo

2
要通过authenticate_user!,您需要包含并使用Devise测试助手,如下所示: https://github.com/plataformatec/devise#test-helpers
class ActionController::TestCase
  include Devise::TestHelpers
end

并在您的测试中使用它们:

  test "should show blog" do
    @user = users(:one) # or FactoryGirl.create(:user), or User.create!(email: 'foo@bar.com')
    sign_in @user
    get :show, id: @blog
    assert_response :success
  end

关于CSRF令牌,你的表单是使用form_for还是其他表单构建器构建的?
这些自动将CSRF令牌添加到表单有效载荷中。如果你使用裸的<form>标记创建表单,则必须像这样自己添加它:
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

谢谢,我的应用程序中包含了devise,这就是为什么“get”请求正常工作的原因。csrf token在我的表单和视图中也可以正常工作(我使用simple_forms gem生成)。但是由于单元测试不通过浏览器,所以token缺失,测试失败。我需要一种方法来传递token或者在测试时排除检查。 - Don Giulio
1
你可以将以下代码放在application_controller.rb文件中:skip_before_filter :verify_authenticity_token if Rails.env.test? - Unixmonkey
我其实刚刚发现我可以配置测试环境而不是将config.action_controller.allow_forgery_protection = false,这样做更好,一旦完成后,我就不再收到CSRF警告了,但我仍然收到Completed 401 Unauthorized,所以我猜问题不在于CSRF...我又一次感到困惑。 - Don Giulio
实际上我要更正一下,似乎在测试环境中禁用CRSF是有效的。之前无法工作的一些调用现在可以工作了,而其他一些调用则出现了不同的问题...感谢您的支持。 - Don Giulio

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