Rspec测试重定向到 :back

65
如何在 rspec 中测试redirect_to :back
我收到以下错误信息:

ActionController::RedirectBackError:
在此操作的请求中没有设置HTTP_REFERER,因此无法成功调用redirect_to :back。 如果这是一个测试,请确保指定request.env["HTTP_REFERER"]

我该如何在我的测试中设置HTTP_REFERER

可能看到测试源代码本身会很有用。这可能是另一个问题的症状... - user483040
我能够通过首先调用“visit root_path”来缓解这个错误。但我认为我只能在集成测试中这样做。是这样吗? - Cyrus
6个回答

119

在使用 RSpec 进行测试时,您可以在 before 块中设置 referer。当我尝试直接在测试中设置 referer 时,无论我将其放在哪里似乎都不起作用,但是在 before 块中设置就可以。

describe BackController < ApplicationController do
  before(:each) do
    request.env["HTTP_REFERER"] = "where_i_came_from"
  end

  describe "GET /goback" do
    it "redirects back to the referring page" do
      get 'goback'
      response.should redirect_to "where_i_came_from"
    end
  end
end

4
我发现使用这个代码是一个不错的主意:request.env["HTTP_REFERER"] = "where_i_came_from" unless request.nil? or request.env.nil?。它的作用是,当请求(request)不为空且请求环境(request.env)不为空时,将HTTP Referer设置为"where_i_came_from"。 - jcollum
是的,对我来说它总是空的,而且根本不起作用。看起来像是一个巨大的错误。 - Robert Reiz
1
自从这个答案被创建以来,可能已经更新以解决此问题,但我能够在测试中成功设置request.env["HTTP_REFERER"]而不使用before块。 - Nick

5

如果有人偶然看到这篇文章并正在使用request规范,那么您需要在进行请求时明确设置请求头。测试请求的格式取决于您使用的RSpec版本以及是否可以使用关键字参数而不是位置参数。

let(:headers){ { "HTTP_REFERER" => "/widgets" } }

it "redirects back to widgets" do 
  post "/widgets", params: {}, headers: headers # keyword (better)
  post "/widgets", {}, headers                  # positional

  expect(response).to redirect_to(widgets_path)
end

https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec


4

以下是从Rails指南中关于使用新的请求样式进行请求时的内容:

describe BackController < ApplicationController do
  describe "GET /goback" do
    it "redirects back to the referring page" do
      get :show, 
        params: { id: 12 },
        headers: { "HTTP_REFERER" => "http://example.com/home" }
      expect(response).to redirect_to("http://example.com/home")
    end
  end
end

3

在我看来,被接受的答案有点麻烦。更好的选择是将HTTP_REFERER设置为应用程序中的实际URL,然后期望被重定向回来:

describe BackController, type: :controller do
  before(:each) do
    request.env['HTTP_REFERER'] = root_url
  end

  it 'redirects back' do
    get :whatever
    response.should redirect_to :back
  end
end
  • 将重定向到随机字符串常量的操作看起来像是偶然发生的
  • 您可以利用rspec内置的功能来精确表达您想要的内容
  • 您不需要引入和重复使用魔法字符串值

对于较新版本的rspec,您可以改用expectations:

expect(response).to redirect_to :back

1
关于测试集成测试中的反向链接,我首先访问一个死链接页面,我认为这个页面不太可能被用作链接,然后再访问我要测试的页面。因此,我的代码看起来像这样:
   before(:each) do
       visit deadend_path
       visit testpage_path
    end
    it "testpage Page should have a Back button going :back" do
      response.should have_selector("a",:href => deadend_path,
                                        :content => "Back")
    end

然而,这种方法的缺陷在于,如果链接确实指向死路,则测试将错误地通过。


-2
request.env['HTTP_REFERER'] = '/your_referring_url'

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