Подтвердить что ты не робот

RSpec: как заглушить унаследованный метод current_user (без разработки)?

У меня есть контроллер на основе MHartl RoR4 Tutorial

И так же, как MHartl, я не использую Devise, я развернул свою собственную систему аутентификации

Возникли проблемы с RSpec для UsersController#Edit, поскольку представление имеет вызов current_user.admin?, а контроллер вызывает @path_switch = path_switch

Я продолжаю получать ошибки RSpec по типу:

1) User Pages Edit 
 Failure/Error: visit edit_user_path(user)
 NoMethodError:
   undefined method 'admin?' for nil:NilClass
 # ./app/controllers/users_controller.rb:106:in 'path_switch'
 # ./app/controllers/users_controller.rb:53:in 'edit'
 # ./spec/requests/user_pages_spec.rb:54:in 'block (3 levels) in <top (required)>'

UsersController:

class UsersController < ApplicationController
  ...
  def edit
    @user = User.find(params[:id])
    @path_switch ||= path_switch                        #error
  end
  ...
  def path_switch
    if current_user.admin?                               #error
      users_path
    else
      root_path
    end
  end
end

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

Здесь, насколько я получил (обновлено):

user_pages_spec.rb:

require 'spec_helper'
require 'support/utilities'

describe "User Pages" do
  #include SessionsHelper

  let(:user) { FactoryGirl.create(:user) }
  let(:current_user) {user}

  subject { page }

  describe "Edit" do
    before do
      sign_in(user)
      visit edit_user_path(user) 
    end

    it '(check links and content)' do
      should have_button('Submit')
      should have_link('Cancel')
      should have_content(user.fname+"\ profile")
    end
   ...
  end
...
end

Но current_user все еще возвращается nil

Любая помощь/руководство приветствуется. Спасибо!


Добавление include SessionsHelper в верхний блок описания моего user_pages_edit.rb, похоже, пытается использовать sign_in (путь) от этого помощника. Создание проблемы между RSpec и cookies.permanent. Так что перебор.

к сожалению, это возвращает меня к моей ошибке .admin?.

Есть два вызова current_user.admin?

Один из них находится в контроллере:

  def path_switch
    if current_user.admin?    #error current_user == nil
      users_path
    else
      root_path
    end
  end

Один вид как ERB:

<% if current_user.admin? %>
  <div class="row  col-xs-6 col-sm-6 col-md-3">
    <div class="input-group input-selector">
    ...

Все, что мне нужно сделать, это выяснить, как установить current_user.admin = true и передать его контроллеру (а затем, надеюсь, представлению), чтобы страница могла загружаться. Для этого все, что мне нужно сделать, это установить current_user = user, потому что user.admin == true.

4b9b3361

Ответ 1

Также работает

user = create(:user) #FactoryBot

allow(controller).to receive(:current_user).and_return(user)

Ответ 2

Если вы выполняете модульное тестирование вашего контроллера, вы можете просто заглушить current_user в блоке до этого, например:

let(:user) { ... }

# RSpec version <= 2 syntax:
before { controller.stub(:current_user) { user } }

# RSpec version >= 3 syntax:
before { allow(controller).to receive(:current_user) { user } }

Если вы выполняете функцию или запрашиваете тестирование, я советую вам выполнить реальный вход в систему, создав пользователя в своей базе данных, а затем пройдя через страницу входа с этими учетными данными пользователя


Здесь вы, кажется, выполняете тест функции, вы должны написать помощника, который выполняет создание пользовательской записи и проходит через вход.

Кроме того, при тестировании функций, чтобы получить много времени при запуске теста, не стесняйтесь группировать свои утверждения в том же блоке. Очевидно, вместо:

it { should have_button('Submit')}
it { should have_link('Cancel')}
it { should have_content(user.fname+"\ profile")}

Вы можете написать

it 'check links and content' do
  should have_button('Submit')
  should have_link('Cancel')
  should have_content(user.fname+"\ profile")
end

Это позволит избежать нескольких сеансов вашей функциональной среды, а также для входа в систему несколько раз

Ответ 3

Для меня работала с:

before { controller.stub!(:current_user).and_return(user) }

Ответ 4

Я столкнулся с той же проблемой с унаследованным приложением Rails 4 и основал свое решение на этом тестовом примере Rspec Views.

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

# /spec/support/concerns/view_helper.rb
module ViewHelper
  def include_current_user_helper(&block)
    controller.singleton_class.class_eval do
      define_method :current_user, &block
      helper_method :current_user
    end
  end
end

Затем настройте Rspec для включения его во все помощники вида

# spec/rails_helper.rb
# ...
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

RSpec.configure do |config|
  # ...
  config.include ViewHelper, type: :view
end

И в спецификации вида это называется так

RSpec.describe 'something' do
  let!(:user) { FactoryGirl.create(:user) } # Note the "!" there
  before { include_current_user_helper { user } }

  # do stuff
end

Примечание: вызов let с грохотом важен, так как содержимое внутри блока будет выполняться лениво, вне области тестирования, и пользователь будет нулевым, если нет