ошибка проверки контроллера rspec неопределенный метод для nil:NilClass

StackOverflow https://stackoverflow.com//questions/24001333

Вопрос

Я новичок в Rspec и пытаюсь разобраться во всем мышлении BDD, поэтому я довольно озадачен этой ошибкой.У меня есть движок have rails, который я пытаюсь протестировать.Вот диспетчер бюллетеней.В принципе, перед любым действием я хочу заполнить список курсов.

class BulletinsController < ApplicationController
  before_filter :get_courses

  def new
    @bulletin = Bulletin.new(author_id: @user.id)
  end

 ...

 private
 def get_courses
   if @user.has_role? :admin
     @course_list = Course.all.sort_by(&:start_date)
   ...
   end
 end

У контроллера приложения есть несколько методов, которые я хочу запускать при каждом запросе.Я использую devise в главном приложении, поэтому у меня есть доступ к методу current_user

class ApplicationController < ::ApplicationController
  before_filter :get_user
  ...
  def get_user
    @user = current_user
  end
  ...
end

И вот спецификация, которую я пытаюсь запустить:

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { controller.stub(:authenticate_user!).and_return true }
  before { controller.stub(:get_user).and_return (@user = create(:user)) }

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end

Когда я пытаюсь запустить спецификацию, я получаю сообщение об ошибке:

NoMethodError: undefined method 'id' for nil:NilClass

Я понимаю, что получаю это потому, что @user не определен, когда он вызывается в здании бюллетеня;однако я думал, что блок before в спецификации определит переменную @user после отключения фильтра :get_user.Когда я тестирую фабрики в консоли, кажется, что все создано с соответствующими ассоциациями (бюллетень -> автор, бюллетень -> курс и т.д.).

Я не уверен, чего мне не хватает относительно того, почему переменная @user не переносится в мой код контроллера.Мы были бы очень признательны за любую информацию и / или хорошие учебные пособия для rspec.

Это было полезно?

Решение

Я думаю, вам также нужно заглушить current_user и этого будет достаточно (не нужно заглушки get_user):

before { controller.stub(:current_user).and_return (@user = create(:user)) }

И я думаю, что хорошей практикой является позволить пользователю (если вам это нужно более одного раза):

routes { MyEngine::Engine.routes }
let!(:user) { create(:user) }
before { controller.stub(:current_user).and_return user }

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

subject.send(:current_user=, user)

Могло бы быть controller вместо subject, не уверен, какую версию поддерживает.

Обновление.На самом деле, тестировать частные методы действительно сложно.Я проверил, что current_user в devise определяет как:

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

Итак, вы можете попробовать stub warden.authenticate к возвратам user:

allow_any_instance_of(Warden).to receive(:authenticate).and_return(create(:user))

Другие советы

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

Рекомендовать способ тестирования - просто подписать пользователь, используя Devise Test Helper в соответствии с их документацией: https://github.com/plataformateC/devise#test-helpers

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { sign_in(user) }

  let!(:user) { create(:user) }

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end
.

Таким образом, вам не придется заботиться о разработке методов и окуривать его.Просто сосредоточиться на тестировании вашего собственного метода.:)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top