2017-04-07 2 views
0

레일즈 4.2.7을 사용하여 장난감 채팅 응용 프로그램을 구축하고 컨트롤러에 대한 사양을 작성 중입니다. rspec 3.5를 사용합니다. 내 Api::ChatroomsController은 대화방을 만들려면 사용자가 로그인해야하므로 Api::ChatroomsController 사양에서 세션을 만들려면 Api::SessionsHelper 모듈을 만들었습니다.레일 4 rspec 3 컨트롤러 테스트 : 세션 도우미 모듈이 이전에 작동하지 않음 (: all), 이전 (: each)

# app/helpers/api/sessions_helper.rb 
module Api::SessionsHelper 
    def current_user 
    User.find_by_session_token(session[:session_token]) 
    end 

    def create_session(user) 
    session[:session_token] = user.reset_session_token! 
    end 

    def destroy_session(user) 
    current_user.try(:reset_session_token!) 
    session[:session_token] = nil 
    end 
end 


# spec/controllers/api/chatrooms_controller_spec.rb 
require 'rails_helper' 
include Api::SessionsHelper 

RSpec.describe Api::ChatroomsController, type: :controller do 
    before(:all) do 
    DatabaseCleaner.clean 
    User.create!({username: "test_user", password: "asdfasdf"}) 
    end 

    user = User.find_by_username("test_user") 

    context "with valid params" do 
    done = false 

    # doesn't work if using a before(:all) hook 
    before(:each) do 
     until done do 
     create_session(user) 
     post :create, chatroom: { name: "chatroom 1" } 
     done = true 
     end 
    end 

    let(:chatroom) { Chatroom.find_by({name: "chatroom 1"}) } 
    let(:chatroom_member) { ChatroomMember.find_by({user_id: user.id, chatroom_id: chatroom.id}) } 

    it "responds with a successful status code" do 
     expect(response).to have_http_status(200) 
    end 

    it "creates a chatroom in the database" do 
     expect(chatroom).not_to eq(nil) 
    end 

    it "adds the chatroom creator to the ChatroomMember table" do 
     expect(chatroom_member).not_to eq(nil) 
    end 
    end 

end 

나는 하나의 세션을 생성하기위한 before(:all) 후크의 동작을 달성하기 위해 부울 변수 donebefore(:each) 후크를 사용하고 있습니다. (모든) 내가 전에 사용하는 경우

는 :

NoMethodError: undefined method `session' for nil:NilClass` 

내가 API를 :: SessionsHelper 모듈 self.class을 확인의 create_session 방법과 두 경우 모두 디버거를 넣어 후크, 나는 오류 내가 before(:each)를 사용하고 내가 before(:all)를 사용할 때, 클래스 인 경우 : 그러나

RSpec::ExampleGroups::ApiChatroomsController::WithValidParams 

before(:each) 후크를 사용하여, 세션, {} 동안 before(:all) 후크, sessi에서 위에 NoMethodError를 제공합니다.

아무도이 오류의 원인을 알고 있습니까? 당신이 database_cleaner을 넣어야하는 곳도 또한 spec/rails_helper.rb

RSpec.configure do |config| 
    # ... 
    config.include Api::SessionsHelper, type: :controller 
end 

에 공통 사양 도우미를 포함하여 중복을 피할 수

RSpec.describe Api::ChatroomsController, type: :controller do 
    include Api::SessionsHelper 
end 

:

답변

0

당신은 테스트 블록의 도우미를 포함해야 config. 테스트 주문 문제 및 테스트 플 래핑으로 이어질 모든 스펙 사이를 정리하는 데 사용해야합니다.

require 'capybara/rspec' 

#... 

RSpec.configure do |config| 

    config.include Api::SessionsHelper, type: :controller 
    config.use_transactional_fixtures = false 

    config.before(:suite) do 
    if config.use_transactional_fixtures? 
     raise(<<-MSG) 
     Delete line `config.use_transactional_fixtures = true` from rails_helper.rb 
     (or set it to false) to prevent uncommitted transactions being used in 
     JavaScript-dependent specs. 

     During testing, the app-under-test that the browser driver connects to 
     uses a different database connection to the database connection used by 
     the spec. The app's database connection would not be able to access 
     uncommitted transaction data setup over the spec's database connection. 
     MSG 
    end 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    DatabaseCleaner.strategy = :transaction 
    end 

    config.before(:each, type: :feature) do 
    # :rack_test driver's Rack app under test shares database connection 
    # with the specs, so continue to use transaction strategy for speed. 
    driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test 

    if !driver_shares_db_connection_with_specs 
     # Driver is probably for an external browser with an app 
     # under test that does *not* share a database connection with the 
     # specs, so use truncation strategy. 
     DatabaseCleaner.strategy = :truncation 
    end 
    end 

    config.before(:each) do 
    DatabaseCleaner.start 
    end 

    config.append_after(:each) do 
    DatabaseCleaner.clean 
    end 

end 
+0

는 ['let'] (https://www.relishapp.com/rspec/rspec-core/v/2-5/docs/helper를 사용하는 방법을 배워야한다처럼 또한 여러 가지 다른 문제가 있습니다 -methods/let-and-let)을 사용하거나'user = User.find_by_username ("test_user")'와 같은 어휘 행을 사용하십시오. – max

+0

일반적인 방법론도 잘못되었습니다. 설치 및 분해 단계 ('before' 및'after')를 사용하여 슬레이트 청소를 닦은 다음 각 예제를 개별적으로 설정해야합니다. 'before_all'을 사용하여 파일의 모든 예제에서 사용되는 일종의 상태를 설정하는 것은 매우 결함이있는 접근 방식입니다. – max

+0

의견을 보내 주셔서 감사합니다. 스펙을 작성하는 데 상당히 익숙합니다. 컨트롤러가 json 만 렌더링하는 경우'capybara '가 필요합니까? 또한 레일즈 도우미뿐만 아니라 테스트 블록 내에서'include Api :: SessionsHelper'를 옮겨 보았습니다. 그리고 두 경우 모두'before (: all)'에서'create_session'을 사용하려고 할 때 여전히 같은 에러를줍니다. 훅. – nequalszero