我正在使用Rails 4.2.7构建一个玩具聊天应用程序,并且正在使用rspec 3.5为我的控制器编写规范。我的Api::ChatroomsController
要求用户登录才能创建聊天室,因此我创建了一个Api::SessionsHelper
模块,以便在Api::ChatroomsController
规范中创建会话。
# 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(:each)
的{{1}}挂钩来实现done
挂钩的行为,以创建单个会话。
如果我使用before(:all)钩子,我会收到错误:
before(:all)
我在Api :: SessionsHelper模块的create_session方法中放置一个调试器来检查NoMethodError: undefined method `session' for nil:NilClass`
,在这两种情况下,当我使用self.class
时,当我使用before(:each)
时,该类是:
before(:all)
但是,当使用RSpec::ExampleGroups::ApiChatroomsController::WithValidParams
挂钩时,会话为before(:each)
,而在{}
挂钩中,会话会提供上面的before(:all)
。
有人知道造成这个错误的原因吗?
答案 0 :(得分:0)
您需要在测试块中包含帮助程序:
RSpec.describe Api::ChatroomsController, type: :controller do
include Api::SessionsHelper
end
您还可以通过在spec/rails_helper.rb
RSpec.configure do |config|
# ...
config.include Api::SessionsHelper, type: :controller
end
这也是你应该放置database_cleaner配置的地方。您应该在每个规范之间进行清理,而不是之前,因为这将导致测试订购问题和扑动测试。
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