Использование Session, Cookies или Current_something в тестах запросов Rspec - PullRequest
0 голосов
/ 17 мая 2019

Я пытаюсь следовать новому соглашению о тестировании Rails с этим новым проектом, над которым я работаю. Поэтому я настраиваю модульные тесты, запрашиваю тесты и функциональные тесты. Проблема заключается в том, что в тестах на запрос Capybara и информация о сеансе не поддерживаются.

В дополнение к настройке метода current_user в Devise, в моем приложении есть еще один аналогичный метод под названием current_client. Для некоторых моих контроллеров мне нужно проверить, вошел ли в систему current_user. Это работает с Devise authenticate_user! вызывается в before_action. Но для некоторых контроллеров мне также нужно проверить, был ли клиент выбран первым (например, если вы хотите добавить транзакции, их нужно связать с текущим клиентом, над которым выполняется работа).

Поэтому я добавил еще один метод before_action, который проверяет, был ли также выбран клиент. Это хорошо работает в функциональных тестах с Capybara, где я могу имитировать вход пользователя в систему и выбор клиента для обработки. Однако в тесте запроса, это не работает.

Сначала я пытаюсь получить доступ к конечной точке без входа пользователя в систему, и ответ не успешен (как и должно быть), и он перенаправляет на страницу входа. Но тогда мне нужно запустить свои тесты с пользователем, вошедшим в систему И выбранным клиентом. Помощники Devise предоставляют метод sign_in (user). Однако я не могу заставить свой метод current_user работать, и я не могу установить его правильно. Таким образом, эти тесты дают сбой и перенаправляют на другую страницу с просьбой выбрать клиента.

Я уже перепробовал много предложений, которые видел. Как попытка заглушить метод current_client, попытка предоставить информацию о сеансе для вызова GET. Я даже попытался проверить исходный код Devise, чтобы узнать, как они могут имитировать метод current_user в Rspec, и не смог найти, где происходит волшебство.

Вот код

Метод current_client выглядит следующим образом

def current_client
  current_client ||= Client.find(session[:client_id]) if session[:client_id]
  rescue ActiveRecord::RecordNotFound
  current_client = nil
end

Так устанавливается, когда пользователь выбирает клиент для обработки

def set_current_client(client)
  session[:client_id] = client.id
end

Это код в моем тестовом файле. Сначала я создаю 2 пользователей, чтобы я мог проверить, что пользователь 1 не может получить доступ к транзакциям пользователя 2 по линии. (Я использую FactoryBot) Затем я создаю 2 клиента (по одному для каждого пользователя)

RSpec.describe "Rooms", :type => :request do 
  let!(:user) {create(:user)}
  let!(:user2) {create(:user2)}

  let!(:client) {create(:client, user: user)}
  let!(:client) {create(:client, user: user2)}

следующие работы

describe 'User Not Signed In' do 
  describe 'GET #index' do
    subject { get transact_path} 
    it "returns an unsuccessful response" do 
      subject
      expect(response).to_not be_successful
  end

  it "redirects to sign in page" do 
    subject
    expect(response).to redirect_to (new_user_session_path)
  end
end

Следующий не делает. Метод sign_in (user) работает в блоке before, и перенаправление на страницу входа не производится. Однако ответ не был успешным, потому что current_client не установлен, и я попытался установить его многими способами в блоке before без успеха.

describe 'User Signed In' do 
  before do 
    sign_in(user)
  end

describe 'GET #index' do 
  it "returns a successful response" do 
    get transact_path
      expect(response).to be_successful
    end
  end
end

Я понимаю, что лучшие практики отошли от тестов контроллеров, потому что то, что визуализированное представление или назначенная переменная экземпляра не имеет никакого отношения к контроллерам в теории. Но в моем случае я просто пытаюсь проверить свои конечные точки и сейчас не могу, потому что не могу настроить свой current_client.

1 Ответ

0 голосов
/ 20 мая 2019

Я нашел способ обойти это, используя предложенное решение от самого DHH.

Вместо того, чтобы пытаться заглушить переменную current_client или попытаться скомбинировать что-то в пустоте ActionDispatch :: Cookies, вам просто нужносделать вызов POST или GET для любого контроллера, который отвечает за установку моей переменной current_client.

Поэтому для меня было решение поместить следующий код в блок before do

before do
  sign_in(user)
  get select_client_path, params: {id: client.id}
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...