rspec 컨트롤러 테스트 오류 정의되지 않은 nil : nilclass
-
20-12-2019 - |
문제
나는 Rspec의 새로운 것이고 나는 BDD 사고 방식에 들어가려고 노력하고 있으므로이 오류에 대해 꽤 튼튼합니다. 나는 테스트하려는 레일 엔진을 가지고 있습니다. 다음은 게시판입니다. 기본적으로 조치가되기 전에 코스 목록을 채우고 싶습니다.
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
.
응용 프로그램 컨트롤러에는 각 요청에서 실행할 수있는 몇 가지 방법이 있습니다. 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가 게시판에서 호출 될 때 정의되지 않았기 때문에 이것을 얻는 것을 이해합니다. 그러나 Spec의 이전 블록이 get_user 필터를 밖으로 스위킹 한 후 @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
.
그래서 warden.authenticate
를 다시 사용하여 tub user
를 반환 할 수 있습니다.
allow_any_instance_of(Warden).to receive(:authenticate).and_return(create(:user))
. 다른 팁
Devise는 어떻게 작동하는지 이해하지 않는 한, 고안된 방법을 사용할 수있는 방법을 스테이블하려고 할 수 있습니다.
테스트하는 것이 좋습니다. 단순히 사용자가 자신의 문서에 따라 고정 된 테스트 도우미를 사용하여 로그인하는 것입니다. 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
.
이 방법으로, 당신은 방법을 고안하고 그것을 던지는 것을 걱정할 필요가 없습니다.자신의 방법을 테스트하는 데 집중하십시오.:)