Rspec тестирует redirect_to:back

#ruby-on-rails #redirect #rspec #rspec2

#ruby-on-rails #перенаправление #rspec #rspec2

Вопрос:

Как вы тестируете redirect_to :back в rspec?

Я получаю

ActionController::RedirectBackError : В запросе на это действие было задано
No HTTP_REFERER , поэтому redirect_to :back не удалось успешно вызвать. Если это тест, обязательно укажите request.env["HTTP_REFERER"] .

Как мне настроить HTTP_REFERER в моем тесте?

Комментарии:

1. Возможно, было бы полезно посмотреть сам тестовый источник. Это может быть симптомом другой проблемы…

2. Я смог устранить эту ошибку, сначала вызвав ‘visit root_path’. Но я думаю, что могу сделать это только в интеграционном тестировании. Это верно?

Ответ №1:

Используя RSpec, вы можете установить ссылку в before блоке. Когда я попытался установить 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
  

Комментарии:

1. Я обнаружил, что это хорошая идея использовать: request.env["HTTP_REFERER"] = "where_i_came_from" unless request.nil? or request.env.nil?

2. да. для меня это всегда ноль, и это просто не работает. Для меня это выглядит как огромная ошибка.

3. Возможно, он был обновлен для устранения этой проблемы с момента создания этого ответа, но я могу успешно установить request.env["HTTP_REFERER"] в своем тесте без использования before блока.

Ответ №2:

Из руководства 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:

Если кто-то наткнется на это, и они используют 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:

ИМХО, принятый ответ немного взламывает. Лучшей альтернативой было бы установить 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, чтобы выразить именно то, что вы хотели
  • Вы не вводите и не повторяете значения magic string

Для более новых версий rspec вместо этого вы можете использовать ожидания:

 expect(response).to redirect_to :back
  

Ответ №5:

Что касается тестирования: обратные ссылки в интеграционных тестах, я сначала посещаю конечную страницу, которая, как я думаю, вряд ли когда-либо будет использоваться в качестве ссылки, а затем страницу, которую я тестирую. Итак, мой код выглядит следующим образом

    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
  

Однако у этого есть недостаток, заключающийся в том, что если ссылка действительно на deadend_path, то тест будет пройден неправильно.

Ответ №6:

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